# HG changeset patch # User Mads Kiilerich # Date 1580948363 -3600 # Node ID 928bc1d8b279ef8bc80b4fb763ab146488313949 # Parent 460e7d2d1b38606432ba57254649f831d811d4f9# Parent 7fef5132620c6fb168ecdb86926ee2638055b56f Merge from default diff -r 460e7d2d1b38 -r 928bc1d8b279 .hgtags --- a/.hgtags Sun Jan 05 01:19:05 2020 +0100 +++ b/.hgtags Thu Feb 06 01:19:23 2020 +0100 @@ -73,3 +73,6 @@ 60f726162fd6c515bd819feb423be73cad01d7d3 0.4.0rc2 19086c5de05f4984d7a90cd31624c45dd893f6bb 0.4.0 da65398a62fff50f3d241796cbf17acdea2092ef 0.4.1 +bfa0b0a814644f0af3f492d17a9ed169cc3b89fe 0.5.0 +d01a8e92936dbd62c76505432f60efba432e9397 0.5.1 +aa0a637fa6f635a5e024fa56b19ed2a2dacca857 0.5.2 diff -r 460e7d2d1b38 -r 928bc1d8b279 CONTRIBUTORS --- a/CONTRIBUTORS Sun Jan 05 01:19:05 2020 +0100 +++ b/CONTRIBUTORS Thu Feb 06 01:19:23 2020 +0100 @@ -1,15 +1,26 @@ List of contributors to Kallithea project: + Thomas De Schampheleire 2014-2020 + Mads Kiilerich 2016-2020 + Dennis Fink 2020 Andrej Shadura 2012 2014-2017 2019 - Thomas De Schampheleire 2014-2019 Étienne Gilli 2015-2017 2019 - Mads Kiilerich 2016-2019 Allan Nordhøy 2017-2019 ssantos 2018-2019 + Adi Kriegisch 2019 Danni Randeris 2019 Edmund Wong 2019 + Elizabeth Sherrock 2019 + Hüseyin Tunç 2019 + leela <53352@protonmail.com> 2019 Manuel Jacob 2019 + Mateusz Mendel 2019 + Nathan 2019 + Oleksandr Shtalinberg 2019 + Private 2019 + THANOS SIOURDAKIS 2019 Wolfgang Scherer 2019 + Христо Станев 2019 Dominik Ruf 2012 2014-2018 Michal Čihař 2014-2015 2018 Branko Majic 2015 2018 diff -r 460e7d2d1b38 -r 928bc1d8b279 Jenkinsfile --- a/Jenkinsfile Sun Jan 05 01:19:05 2020 +0100 +++ b/Jenkinsfile Thu Feb 06 01:19:23 2020 +0100 @@ -9,10 +9,10 @@ daysToKeepStr: '', numToKeepStr: '']]]); if (isUnix()) { - createvirtualenv = 'rm -r $JENKINS_HOME/venv/$JOB_NAME || true && virtualenv $JENKINS_HOME/venv/$JOB_NAME' + createvirtualenv = 'rm -r $JENKINS_HOME/venv/$JOB_NAME || true && python3 -m venv $JENKINS_HOME/venv/$JOB_NAME' activatevirtualenv = '. $JENKINS_HOME/venv/$JOB_NAME/bin/activate' } else { - createvirtualenv = 'rmdir /s /q %JENKINS_HOME%\\venv\\%JOB_NAME% || true && virtualenv %JENKINS_HOME%\\venv\\%JOB_NAME%' + createvirtualenv = 'rmdir /s /q %JENKINS_HOME%\\venv\\%JOB_NAME% || true && python3 -m venv %JENKINS_HOME%\\venv\\%JOB_NAME%' activatevirtualenv = 'call %JENKINS_HOME%\\venv\\%JOB_NAME%\\Scripts\\activate.bat' } diff -r 460e7d2d1b38 -r 928bc1d8b279 MANIFEST.in --- a/MANIFEST.in Sun Jan 05 01:19:05 2020 +0100 +++ b/MANIFEST.in Thu Feb 06 01:19:23 2020 +0100 @@ -7,6 +7,7 @@ include LICENSE.md include MIT-Permissive-License.txt include README.rst +include conftest.py include dev_requirements.txt include development.ini include pytest.ini diff -r 460e7d2d1b38 -r 928bc1d8b279 README.rst --- a/README.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/README.rst Thu Feb 06 01:19:23 2020 +0100 @@ -24,8 +24,8 @@ Installation ------------ -Kallithea requires Python_ 2.7 and it is recommended to install it in a -virtualenv_. Official releases of Kallithea can be installed with:: +Kallithea requires Python_ 3 and it is recommended to install it in a +virtualenv. Official releases of Kallithea can be installed with:: pip install kallithea @@ -173,7 +173,6 @@ of Kallithea. -.. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _Python: http://www.python.org/ .. _Sphinx: http://sphinx.pocoo.org/ .. _Mercurial: http://mercurial.selenic.com/ diff -r 460e7d2d1b38 -r 928bc1d8b279 conftest.py --- a/conftest.py Sun Jan 05 01:19:05 2020 +0100 +++ b/conftest.py Thu Feb 06 01:19:23 2020 +0100 @@ -2,10 +2,19 @@ import mock import pytest +import tg here = os.path.dirname(__file__) +# HACK: +def pytest_configure(): + # Register global dummy tg.context to avoid "TypeError: No object (name: context) has been registered for this thread" + tg.request_local.context._push_object(tg.util.bunch.Bunch()) + # could be removed again after use with + # tg.request_local.context._pop_object ... but we keep it around forever as + # a reasonable sentinel + def pytest_ignore_collect(path): # ignore all files outside the 'kallithea' directory if not str(path).startswith(os.path.join(here, 'kallithea')): @@ -36,3 +45,10 @@ m = __import__(request.module.__name__, globals(), locals(), [None], 0) with mock.patch.object(m, '_', lambda s: s): yield + +if getattr(pytest, 'register_assert_rewrite', None): + # make sure that all asserts under kallithea/tests benefit from advanced + # assert reporting with pytest-3.0.0+, including api/api_base.py, + # models/common.py etc. + # See also: https://docs.pytest.org/en/latest/assert.html#advanced-assertion-introspection + pytest.register_assert_rewrite('kallithea.tests') diff -r 460e7d2d1b38 -r 928bc1d8b279 dev_requirements.txt --- a/dev_requirements.txt Sun Jan 05 01:19:05 2020 +0100 +++ b/dev_requirements.txt Thu Feb 06 01:19:23 2020 +0100 @@ -4,5 +4,5 @@ pytest-localserver >= 0.5.0, < 0.6 mock >= 3.0.0, < 3.1 Sphinx >= 1.8.0, < 1.9 -WebTest >= 2.0.3, < 2.1 +WebTest >= 2.0.6, < 2.1 isort == 4.3.21 diff -r 460e7d2d1b38 -r 928bc1d8b279 development.ini --- a/development.ini Sun Jan 05 01:19:05 2020 +0100 +++ b/development.ini Thu Feb 06 01:19:23 2020 +0100 @@ -126,7 +126,7 @@ ## used, which is correct in many cases but for example not when using uwsgi. ## If you change this setting, you should reinstall the Git hooks via ## Admin > Settings > Remap and Rescan. -# git_hook_interpreter = /srv/kallithea/venv/bin/python2 +# git_hook_interpreter = /srv/kallithea/venv/bin/python3 ## path to git executable git_path = git diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/administrator_guide/auth.rst --- a/docs/administrator_guide/auth.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/administrator_guide/auth.rst Thu Feb 06 01:19:23 2020 +0100 @@ -135,10 +135,10 @@ .. _Custom CA Certificates: Custom CA Certificates : optional - Directory used by OpenSSL to find CAs for validating the LDAP server certificate. - Python 2.7.10 and later default to using the system certificate store, and - this should thus not be necessary when using certificates signed by a CA - trusted by the system. + Directory used by OpenSSL to find CAs for validating the LDAP server + certificate. It defaults to using the system certificate store, and it + should thus not be necessary to specify *Custom CA Certificates* when using + certificates signed by a CA trusted by the system. It can be set to something like `/etc/openldap/cacerts` on older systems or if using self-signed certificates. diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/conf.py --- a/docs/conf.py Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/conf.py Thu Feb 06 01:19:23 2020 +0100 @@ -47,7 +47,7 @@ # General information about the project. project = u'Kallithea' -copyright = u'2010-2019 by various authors, licensed as GPLv3.' +copyright = u'2010-2020 by various authors, licensed as GPLv3.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/contributing.rst --- a/docs/contributing.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/contributing.rst Thu Feb 06 01:19:23 2020 +0100 @@ -32,7 +32,7 @@ hg clone https://kallithea-scm.org/repos/kallithea cd kallithea - virtualenv ../kallithea-venv + python3 -m venv ../kallithea-venv source ../kallithea-venv/bin/activate pip install --upgrade pip setuptools pip install --upgrade -e . -r dev_requirements.txt python-ldap python-pam @@ -92,8 +92,7 @@ and the test suite creates repositories in the temporary directory. Linux systems with /tmp mounted noexec will thus fail. -You can also use ``tox`` to run the tests with all supported Python versions -(currently only Python 2.7). +You can also use ``tox`` to run the tests with all supported Python versions. When running tests, Kallithea generates a `test.ini` based on template values in `kallithea/tests/conftest.py` and populates the SQLite database specified @@ -199,8 +198,7 @@ consistency with existing code. Run ``scripts/run-all-cleanup`` before committing to ensure some basic code formatting consistency. -We currently only support Python 2.7.x and nothing else. For now we don't care -about Python 3 compatibility. +We support Python 3.6 and later. We try to support the most common modern web browsers. IE9 is still supported to the extent it is feasible, IE8 is not. diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/index.rst --- a/docs/index.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/index.rst Thu Feb 06 01:19:23 2020 +0100 @@ -78,7 +78,6 @@ dev/dbmigrations -.. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _python: http://www.python.org/ .. _django: http://www.djangoproject.com/ .. _mercurial: https://www.mercurial-scm.org/ diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/installation.rst --- a/docs/installation.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/installation.rst Thu Feb 06 01:19:23 2020 +0100 @@ -35,12 +35,12 @@ For Debian and Ubuntu, the following command will ensure that a reasonable set of dependencies is installed:: - sudo apt-get install build-essential git python-pip python-virtualenv libffi-dev python-dev + sudo apt-get install build-essential git libffi-dev python3-dev For Fedora and RHEL-derivatives, the following command will ensure that a reasonable set of dependencies is installed:: - sudo yum install gcc git python-pip python-virtualenv libffi-devel python-devel + sudo yum install gcc git libffi-devel python3-devel .. _installation-source: @@ -48,16 +48,16 @@ Installation from repository source ----------------------------------- -To install Kallithea in a virtualenv_ using the stable branch of the development +To install Kallithea in a virtualenv using the stable branch of the development repository, follow the instructions below:: hg clone https://kallithea-scm.org/repos/kallithea -u stable cd kallithea - virtualenv ../kallithea-venv + python3 -m venv ../kallithea-venv . ../kallithea-venv/bin/activate pip install --upgrade pip setuptools pip install --upgrade -e . - python2 setup.py compile_catalog # for translation of the UI + python3 setup.py compile_catalog # for translation of the UI You can now proceed to :ref:`setup`. @@ -67,18 +67,18 @@ Installing a released version in a virtualenv --------------------------------------------- -It is highly recommended to use a separate virtualenv_ for installing Kallithea. +It is highly recommended to use a separate virtualenv for installing Kallithea. This way, all libraries required by Kallithea will be installed separately from your main Python installation and other applications and things will be less problematic when upgrading the system or Kallithea. -An additional benefit of virtualenv_ is that it doesn't require root privileges. +An additional benefit of virtualenv is that it doesn't require root privileges. -- Assuming you have installed virtualenv_, create a new virtual environment - for example, in `/srv/kallithea/venv`, using the virtualenv command:: +- Assuming you have installed virtualenv, create a new virtual environment + for example, in `/srv/kallithea/venv`, using the venv command:: - virtualenv /srv/kallithea/venv + python3 -m venv /srv/kallithea/venv -- Activate the virtualenv_ in your current shell session and make sure the +- Activate the virtualenv in your current shell session and make sure the basic requirements are up-to-date by running:: . /srv/kallithea/venv/bin/activate @@ -133,6 +133,3 @@ pip install --user kallithea You can now proceed to :ref:`setup`. - - -.. _virtualenv: http://pypi.python.org/pypi/virtualenv diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/installation_iis.rst --- a/docs/installation_iis.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/installation_iis.rst Thu Feb 06 01:19:23 2020 +0100 @@ -1,5 +1,7 @@ .. _installation_iis: +.. warning:: This section is outdated and needs updating for Python 3. + ===================================================================== Installing Kallithea on Microsoft Internet Information Services (IIS) ===================================================================== @@ -66,7 +68,7 @@ has been generated, it is necessary to run the following command due to the way that ISAPI-WSGI is made:: - python2 dispatch.py install + python3 dispatch.py install This accomplishes two things: generating an ISAPI compliant DLL file, ``_dispatch.dll``, and installing a script map handler into IIS for the @@ -119,7 +121,7 @@ In order to dump output from WSGI using ``win32traceutil`` it is sufficient to type the following in a console window:: - python2 -m win32traceutil + python3 -m win32traceutil and any exceptions occurring in the WSGI layer and below (i.e. in the Kallithea application itself) that are uncaught, will be printed here complete with stack diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/installation_win.rst --- a/docs/installation_win.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/installation_win.rst Thu Feb 06 01:19:23 2020 +0100 @@ -1,5 +1,7 @@ .. _installation_win: +.. warning:: This section is outdated and needs updating for Python 3. + ==================================================== Installation on Windows (7/Server 2008 R2 and newer) ==================================================== @@ -17,18 +19,16 @@ Step 1 -- Install Python ^^^^^^^^^^^^^^^^^^^^^^^^ -Install Python 2.7.x. Latest version is recommended. If you need another version, they can run side by side. +Install Python 3. Latest version is recommended. If you need another version, they can run side by side. -.. warning:: Python 3.x is not supported. - -- Download Python 2.7.x from http://www.python.org/download/ +- Download Python 3 from http://www.python.org/download/ - Choose and click on the version - Click on "Windows X86-64 Installer" for x64 or "Windows x86 MSI installer" for Win32. - Disable UAC or run the installer with admin privileges. If you chose to disable UAC, do not forget to reboot afterwards. -While writing this guide, the latest version was v2.7.9. +While writing this guide, the latest version was v3.8.1. Remember the specific major and minor versions installed, because they will -be needed in the next step. In this case, it is "2.7". +be needed in the next step. In this case, it is "3.8". Step 2 -- Python BIN ^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ SETX PATH "%PATH%;[your-python-path]" /M Please substitute [your-python-path] with your Python installation -path. Typically this is ``C:\\Python27``. +path. Typically this is ``C:\\Python38``. Step 3 -- Install pywin32 extensions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,38 +52,14 @@ - Click on "pywin32" folder - Click on the first folder (in this case, Build 219, maybe newer when you try) -- Choose the file ending with ".amd64-py2.x.exe" (".win32-py2.x.exe" +- Choose the file ending with ".amd64-py3.x.exe" (".win32-py3.x.exe" for Win32) where x is the minor version of Python you installed. When writing this guide, the file was: - http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/pywin32-219.win-amd64-py2.7.exe/download + http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/pywin32-219.win-amd64-py3.8.exe/download (x64) - http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/pywin32-219.win32-py2.7.exe/download + http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/pywin32-219.win32-py3.8.exe/download (Win32) -Step 4 -- Install pip -^^^^^^^^^^^^^^^^^^^^^ - -pip is a package management system for Python. You will need it to install Kallithea and its dependencies. - -If you installed Python 2.7.9+, you already have it (as long as you ran the installer with admin privileges or disabled UAC). - -If it was not installed or if you are using Python < 2.7.9: - -- Go to https://bootstrap.pypa.io -- Right-click on get-pip.py and choose Saves as... -- Run "python2 get-pip.py" in the folder where you downloaded get-pip.py (may require admin access). - -.. note:: - - See http://stackoverflow.com/questions/4750806/how-to-install-pip-on-windows - for details and alternative methods. - -Note that pip.exe will be placed inside your Python installation's -Scripts folder, which is likely not on your path. To correct this, -open a CMD and type:: - - SETX PATH "%PATH%;[your-python-path]\Scripts" /M - Step 5 -- Kallithea folder structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,24 +84,18 @@ A python virtual environment will allow for isolation between the Python packages of your system and those used for Kallithea. It is strongly recommended to use it to ensure that Kallithea does not change a dependency that other software uses or vice versa. -In a command prompt type:: - - pip install virtualenv - -Virtualenv will now be inside your Python Scripts path (C:\\Python27\\Scripts or similar). - To create a virtual environment, run:: - virtualenv C:\Kallithea\Env + python3 -m venv C:\Kallithea\Env Step 7 -- Install Kallithea ^^^^^^^^^^^^^^^^^^^^^^^^^^^ In order to install Kallithea, you need to be able to run "pip install kallithea". It will use pip to install the Kallithea Python package and its dependencies. Some Python packages use managed code and need to be compiled. -This can be done on Linux without any special steps. On Windows, you will need to install Microsoft Visual C++ compiler for Python 2.7. +This can be done on Linux without any special steps. On Windows, you will need to install Microsoft Visual C++ compiler for Python 3.8. -Download and install "Microsoft Visual C++ Compiler for Python 2.7" from http://aka.ms/vcpython27 +Download and install "Microsoft Visual C++ Compiler for Python 3.8" from http://aka.ms/vcpython27 .. note:: You can also install the dependencies using already compiled Windows binaries packages. A good source of compiled Python packages is http://www.lfd.uci.edu/~gohlke/pythonlibs/. However, not all of the necessary packages for Kallithea are on this site and some are hard to find, so we will stick with using the compiler. diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/installation_win_old.rst --- a/docs/installation_win_old.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/installation_win_old.rst Thu Feb 06 01:19:23 2020 +0100 @@ -1,5 +1,7 @@ .. _installation_win_old: +.. warning:: This section is outdated and needs updating for Python 3. + ========================================================== Installation on Windows (XP/Vista/Server 2003/Server 2008) ========================================================== @@ -60,14 +62,11 @@ Step 2 -- Install Python ^^^^^^^^^^^^^^^^^^^^^^^^ -Install Python 2.7.x x86 version (32-bit). DO NOT USE A 3.x version. -Download Python 2.7.x from: +Install Python 3.8.x from: http://www.python.org/download/ -Choose "Windows Installer" (32-bit version) not "Windows X86-64 -Installer". While writing this guide, the latest version was v2.7.3. Remember the specific major and minor version installed, because it will -be needed in the next step. In this case, it is "2.7". +be needed in the next step. In this case, it is "3.8". .. note:: @@ -80,17 +79,17 @@ http://sourceforge.net/projects/pywin32/files/ - Click on "pywin32" folder -- Click on the first folder (in this case, Build 217, maybe newer when you try) -- Choose the file ending with ".win32-py2.x.exe" -> x being the minor +- Click on the first folder (in this case, Build 218, maybe newer when you try) +- Choose the file ending with ".win32-py3.x.exe" -> x being the minor version of Python you installed (in this case, 7) When writing this guide, the file was: - http://sourceforge.net/projects/pywin32/files/pywin32/Build%20217/pywin32-217.win32-py2.7.exe/download + http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win-amd64-py3.8.exe/download .. note:: 64-bit: Download and install the 64-bit version. At the time of writing you can find this at: - http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win-amd64-py2.7.exe/download + http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win-amd64-py3.8.exe/download Step 4 -- Python BIN ^^^^^^^^^^^^^^^^^^^^ @@ -117,7 +116,7 @@ SETX PATH "%PATH%;[your-python-path]" /M Please substitute [your-python-path] with your Python installation path. - Typically: C:\\Python27 + Typically: C:\\Python38 Step 5 -- Kallithea folder structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -139,22 +138,10 @@ Step 6 -- Install virtualenv ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Install Virtual Env for Python - -Navigate to: http://www.virtualenv.org/en/latest/index.html#installation -Right click on "virtualenv.py" file and choose "Save link as...". -Download to C:\\Kallithea (or whatever you want) -(the file is located at -https://raw.github.com/pypa/virtualenv/master/virtualenv.py) +Create a virtual Python environment in C:\\Kallithea\\Env (or similar). To +do so, open a CMD (Python Path should be included in Step3), and write:: -Create a virtual Python environment in C:\\Kallithea\\Env (or similar). To -do so, open a CMD (Python Path should be included in Step3), navigate -where you downloaded "virtualenv.py", and write:: - - python2 virtualenv.py C:\Kallithea\Env - -(--no-site-packages is now the default behaviour of virtualenv, no need -to include it) + python3 -m venv C:\Kallithea\Env Step 7 -- Install Kallithea ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/overview.rst --- a/docs/overview.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/overview.rst Thu Feb 06 01:19:23 2020 +0100 @@ -12,7 +12,7 @@ ------------------ **Kallithea** is written entirely in Python_ and requires Python version -2.7 or higher. Python 3.x is currently not supported. +3.6 or higher. Given a Python installation, there are different ways of providing the environment for running Python applications. Each of them pretty much @@ -30,7 +30,7 @@ - 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 +- 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. @@ -98,7 +98,7 @@ 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/`` + other package, usually as a ``.../site-packages/Kallithea-X-py3.8.egg/`` directory with Python files and everything else that is needed. (``pip install kallithea`` from a source tree will do pretty much the same @@ -165,7 +165,6 @@ .. _Python: http://www.python.org/ .. _Gunicorn: http://gunicorn.org/ .. _Waitress: http://waitress.readthedocs.org/en/latest/ -.. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _Gearbox: http://turbogears.readthedocs.io/en/latest/turbogears/gearbox.html .. _PyPI: https://pypi.python.org/pypi .. _Apache httpd: http://httpd.apache.org/ diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/setup.rst --- a/docs/setup.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/setup.rst Thu Feb 06 01:19:23 2020 +0100 @@ -557,11 +557,11 @@ os.chdir('/srv/kallithea/') import site - site.addsitedir("/srv/kallithea/venv/lib/python2.7/site-packages") + site.addsitedir("/srv/kallithea/venv/lib/python3.7/site-packages") ini = '/srv/kallithea/my.ini' from logging.config import fileConfig - fileConfig(ini) + fileConfig(ini, {'__file__': ini, 'here': '/srv/kallithea'}) from paste.deploy import loadapp application = loadapp('config:' + ini) @@ -577,7 +577,7 @@ ini = '/srv/kallithea/kallithea.ini' from logging.config import fileConfig - fileConfig(ini) + fileConfig(ini, {'__file__': ini, 'here': '/srv/kallithea'}) from paste.deploy import loadapp application = loadapp('config:' + ini) @@ -624,7 +624,6 @@ .. __: https://kallithea-scm.org/repos/kallithea/files/tip/init.d/ . -.. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _python: http://www.python.org/ .. _Python regular expression documentation: https://docs.python.org/2/library/re.html .. _Mercurial: https://www.mercurial-scm.org/ diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/upgrade.rst --- a/docs/upgrade.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/upgrade.rst Thu Feb 06 01:19:23 2020 +0100 @@ -241,6 +241,3 @@ .. note:: Kallithea does not use hooks on Mercurial repositories. This step is thus not necessary if you only have Mercurial repositories. - - -.. _virtualenv: http://pypi.python.org/pypi/virtualenv diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/usage/performance.rst --- a/docs/usage/performance.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/usage/performance.rst Thu Feb 06 01:19:23 2020 +0100 @@ -23,6 +23,15 @@ Tweak beaker cache settings in the ini file. The actual effect of that is questionable. +.. note:: + + Beaker has no upper bound on cache size and will never drop any caches. For + memory cache, the only option is to regularly restart the worker process. + For file cache, it must be cleaned manually, as described in the `Beaker + documentation `_:: + + find data/cache -type f -mtime +30 -print -exec rm {} \; + Database -------- diff -r 460e7d2d1b38 -r 928bc1d8b279 docs/usage/troubleshooting.rst --- a/docs/usage/troubleshooting.rst Sun Jan 05 01:19:05 2020 +0100 +++ b/docs/usage/troubleshooting.rst Thu Feb 06 01:19:23 2020 +0100 @@ -8,7 +8,7 @@ :A: Make sure either to set the ``static_files = true`` in the .ini file or double check the root path for your http setup. It should point to for example: - ``/home/my-virtual-python/lib/python2.7/site-packages/kallithea/public`` + ``/home/my-virtual-python/lib/python3.7/site-packages/kallithea/public`` | @@ -67,7 +67,6 @@ you have installed the latest Windows patches (especially KB2789397). -.. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _python: http://www.python.org/ .. _mercurial: https://www.mercurial-scm.org/ .. _celery: http://celeryproject.org/ diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/__init__.py --- a/kallithea/__init__.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/__init__.py Thu Feb 06 01:19:23 2020 +0100 @@ -31,7 +31,10 @@ import sys -VERSION = (0, 4, 99) +if sys.version_info < (3, 6): + raise Exception('Kallithea requires python 3.6 or later') + +VERSION = (0, 5, 99) BACKENDS = { 'hg': 'Mercurial repository', 'git': 'Git repository', diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/alembic/env.py --- a/kallithea/alembic/env.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/alembic/env.py Thu Feb 06 01:19:23 2020 +0100 @@ -15,6 +15,7 @@ # Alembic migration environment (configuration). import logging +import os from logging.config import fileConfig from alembic import context @@ -43,7 +44,9 @@ # stamping during "kallithea-cli db-create"), config_file_name is not available, # and loggers are assumed to already have been configured. if config.config_file_name: - fileConfig(config.config_file_name, disable_existing_loggers=False) + fileConfig(config.config_file_name, + {'__file__': config.config_file_name, 'here': os.path.dirname(config.config_file_name)}, + disable_existing_loggers=False) def include_in_autogeneration(object, name, type, reflected, compare_to): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/alembic/versions/151b4a4e8c48_db_migration_step_after_93834966ae01_.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/alembic/versions/151b4a4e8c48_db_migration_step_after_93834966ae01_.py Thu Feb 06 01:19:23 2020 +0100 @@ -0,0 +1,51 @@ +# 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 . + +"""db: migration step after 93834966ae01 dropped non-nullable inherit_default_permissions + +Revision ID: 151b4a4e8c48 +Revises: b74907136bc1 +Create Date: 2019-11-23 01:37:42.963119 + +""" + +# The following opaque hexadecimal identifiers ("revisions") are used +# by Alembic to track this migration script and its relations to others. +revision = '151b4a4e8c48' +down_revision = 'b74907136bc1' +branch_labels = None +depends_on = None + +import sqlalchemy as sa +from alembic import op + + +def upgrade(): + meta = sa.MetaData() + meta.reflect(bind=op.get_bind()) + + if 'inherit_default_permissions' in meta.tables['users'].columns: + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.drop_column('inherit_default_permissions') + + if 'users_group_inherit_default_permissions' in meta.tables['users_groups'].columns: + with op.batch_alter_table('users_groups', schema=None) as batch_op: + batch_op.drop_column('users_group_inherit_default_permissions') + + +def downgrade(): + with op.batch_alter_table('users_groups', schema=None) as batch_op: + batch_op.add_column(sa.Column('users_group_inherit_default_permissions', sa.BOOLEAN(), nullable=False, default=True)) + + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.add_column(sa.Column('inherit_default_permissions', sa.BOOLEAN(), nullable=False, default=True)) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/alembic/versions/4851d15bc437_db_migration_step_after_95c01895c006_.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/alembic/versions/4851d15bc437_db_migration_step_after_95c01895c006_.py Thu Feb 06 01:19:23 2020 +0100 @@ -0,0 +1,51 @@ +# 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 . + +"""db: migration step after 95c01895c006 failed to add usk_public_key_idx in alembic step b74907136bc1 + +Revision ID: 4851d15bc437 +Revises: 151b4a4e8c48 +Create Date: 2019-11-24 02:51:14.029583 + +""" + +# The following opaque hexadecimal identifiers ("revisions") are used +# by Alembic to track this migration script and its relations to others. +revision = '4851d15bc437' +down_revision = '151b4a4e8c48' +branch_labels = None +depends_on = None + +import sqlalchemy as sa +from alembic import op + + +def upgrade(): + pass + # The following upgrade step turned out to be a bad idea. A later step + # "d7ec25b66e47_ssh_drop_usk_public_key_idx_again" will remove the index + # again if it exists ... but we shouldn't even try to create it. + + #meta = sa.MetaData() + #meta.reflect(bind=op.get_bind()) + + #if not any(i.name == 'usk_public_key_idx' for i in meta.tables['user_ssh_keys'].indexes): + # with op.batch_alter_table('user_ssh_keys', schema=None) as batch_op: + # batch_op.create_index('usk_public_key_idx', ['public_key'], unique=False) + + +def downgrade(): + meta = sa.MetaData() + if any(i.name == 'usk_public_key_idx' for i in meta.tables['user_ssh_keys'].indexes): + with op.batch_alter_table('user_ssh_keys', schema=None) as batch_op: + batch_op.drop_index('usk_public_key_idx') diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/alembic/versions/d7ec25b66e47_ssh_drop_usk_public_key_idx_again.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/alembic/versions/d7ec25b66e47_ssh_drop_usk_public_key_idx_again.py Thu Feb 06 01:19:23 2020 +0100 @@ -0,0 +1,43 @@ +# 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 . + +"""ssh: drop usk_public_key_idx again + +Revision ID: d7ec25b66e47 +Revises: 4851d15bc437 +Create Date: 2019-12-29 15:33:10.982003 + +""" + +# The following opaque hexadecimal identifiers ("revisions") are used +# by Alembic to track this migration script and its relations to others. +revision = 'd7ec25b66e47' +down_revision = '4851d15bc437' +branch_labels = None +depends_on = None + +import sqlalchemy as sa +from alembic import op + + +def upgrade(): + meta = sa.MetaData() + meta.reflect(bind=op.get_bind()) + + if any(i.name == 'usk_public_key_idx' for i in meta.tables['user_ssh_keys'].indexes): + with op.batch_alter_table('user_ssh_keys', schema=None) as batch_op: + batch_op.drop_index('usk_public_key_idx') + + +def downgrade(): + pass diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/base.py --- a/kallithea/bin/base.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/base.py Thu Feb 06 01:19:23 2020 +0100 @@ -29,9 +29,10 @@ import pprint import random import sys -import urllib2 +import urllib.request -from kallithea.lib.compat import json +from kallithea.lib import ext_json +from kallithea.lib.utils2 import ascii_bytes CONFIG_NAME = '.config/kallithea' @@ -67,12 +68,12 @@ raise Exception('please specify method name !') apihost = apihost.rstrip('/') id_ = random.randrange(1, 9999) - req = urllib2.Request('%s/_admin/api' % apihost, - data=json.dumps(_build_data(id_)), + req = urllib.request.Request('%s/_admin/api' % apihost, + data=ascii_bytes(ext_json.dumps(_build_data(id_))), headers={'content-type': 'text/plain'}) - ret = urllib2.urlopen(req) + ret = urllib.request.urlopen(req) raw_json = ret.read() - json_data = json.loads(raw_json) + json_data = ext_json.loads(raw_json) id_ret = json_data['id'] if id_ret == id_: return json_data @@ -107,7 +108,7 @@ def __getitem__(self, key): return self._conf[key] - def __nonzero__(self): + def __bool__(self): if self._conf: return True return False @@ -128,7 +129,7 @@ if os.path.exists(self._conf_name): update = True with open(self._conf_name, 'wb') as f: - json.dump(config, f, indent=4) + ext_json.dump(config, f, indent=4) f.write('\n') if update: @@ -146,7 +147,7 @@ config = {} try: with open(self._conf_name, 'rb') as conf: - config = json.load(conf) + config = ext_json.load(conf) except IOError as e: sys.stderr.write(str(e) + '\n') @@ -159,7 +160,7 @@ """ try: with open(self._conf_name, 'rb') as conf: - return json.load(conf) + return ext_json.load(conf) except IOError as e: #sys.stderr.write(str(e) + '\n') pass diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_api.py --- a/kallithea/bin/kallithea_api.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_api.py Thu Feb 06 01:19:23 2020 +0100 @@ -28,9 +28,10 @@ from __future__ import print_function import argparse +import json import sys -from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call, json +from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call def argparser(argv): @@ -101,7 +102,7 @@ parser.error('Please specify method name') try: - margs = dict(map(lambda s: s.split(':', 1), other)) + margs = dict(s.split(':', 1) for s in other) except ValueError: sys.stderr.write('Error parsing arguments \n') sys.exit() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_cli_base.py --- a/kallithea/bin/kallithea_cli_base.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_cli_base.py Thu Feb 06 01:19:23 2020 +0100 @@ -12,7 +12,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import cStringIO +import configparser import functools import logging.config import os @@ -23,6 +23,7 @@ import paste.deploy import kallithea +import kallithea.config.middleware # kallithea_cli is usually invoked through the 'kallithea-cli' wrapper script @@ -71,11 +72,12 @@ def runtime_wrapper(config_file, *args, **kwargs): path_to_ini_file = os.path.realpath(config_file) kallithea.CONFIG = paste.deploy.appconfig('config:' + path_to_ini_file) - config_bytes = read_config(path_to_ini_file, strip_section_prefix=annotated.__name__) - logging.config.fileConfig(cStringIO.StringIO(config_bytes)) + cp = configparser.ConfigParser(strict=False) + cp.read_string(read_config(path_to_ini_file, strip_section_prefix=annotated.__name__)) + logging.config.fileConfig(cp, + {'__file__': path_to_ini_file, 'here': os.path.dirname(path_to_ini_file)}) if config_file_initialize_app: - kallithea.config.middleware.make_app_without_logging(kallithea.CONFIG.global_conf, **kallithea.CONFIG.local_conf) - kallithea.lib.utils.setup_cache_regions(kallithea.CONFIG) + kallithea.config.middleware.make_app(kallithea.CONFIG.global_conf, **kallithea.CONFIG.local_conf) return annotated(*args, **kwargs) return cli_command(runtime_wrapper) return annotator diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_cli_celery.py --- a/kallithea/bin/kallithea_cli_celery.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_cli_celery.py Thu Feb 06 01:19:23 2020 +0100 @@ -16,6 +16,7 @@ import kallithea import kallithea.bin.kallithea_cli_base as cli_base +from kallithea.lib import celerypylons @cli_base.register_command(config_file_initialize_app=True) @@ -35,6 +36,6 @@ raise Exception('Please set use_celery = true in .ini config ' 'file before running this command') - from kallithea.lib import celerypylons - cmd = celerypylons.worker.worker(celerypylons.app) + app = celerypylons.make_app() + cmd = celerypylons.worker.worker(app) return cmd.run_from_argv(None, command='celery-run -c CONFIG_FILE --', argv=list(celery_args)) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_cli_db.py --- a/kallithea/bin/kallithea_cli_db.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_cli_db.py Thu Feb 06 01:19:23 2020 +0100 @@ -67,7 +67,7 @@ Session().commit() # initial repository scan - kallithea.config.middleware.make_app_without_logging( + kallithea.config.middleware.make_app( kallithea.CONFIG.global_conf, **kallithea.CONFIG.local_conf) added, _ = kallithea.lib.utils.repo2db_mapper(kallithea.model.scm.ScmModel().repo_scan()) if added: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_cli_iis.py --- a/kallithea/bin/kallithea_cli_iis.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_cli_iis.py Thu Feb 06 01:19:23 2020 +0100 @@ -33,7 +33,8 @@ def __ExtensionFactory__(): from paste.deploy import loadapp from logging.config import fileConfig - fileConfig('%(inifile)s') + fileConfig('%(inifile)s', {'__file__': '%(inifile)s', 'here': '%(inifiledir)s'}) + application = loadapp('config:%(inifile)s') def app(environ, start_response): @@ -75,6 +76,7 @@ with open(dispatchfile, 'w') as f: f.write(dispath_py_template % { 'inifile': config_file_abs.replace('\\', '\\\\'), + 'inifiledir': os.path.dirname(config_file_abs).replace('\\', '\\\\'), 'virtualdir': virtualdir, }) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_cli_ishell.py --- a/kallithea/bin/kallithea_cli_ishell.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_cli_ishell.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,7 +25,7 @@ import sys import kallithea.bin.kallithea_cli_base as cli_base -from kallithea.model.db import * +from kallithea.model.db import * # these names will be directly available in the IPython shell @cli_base.register_command(config_file_initialize_app=True) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_cli_repo.py --- a/kallithea/bin/kallithea_cli_repo.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_cli_repo.py Thu Feb 06 01:19:23 2020 +0100 @@ -28,7 +28,7 @@ import kallithea.bin.kallithea_cli_base as cli_base from kallithea.lib.utils import REMOVED_REPO_PAT, repo2db_mapper -from kallithea.lib.utils2 import ask_ok, safe_str, safe_unicode +from kallithea.lib.utils2 import ask_ok from kallithea.model.db import Repository, Ui from kallithea.model.meta import Session from kallithea.model.scm import ScmModel @@ -74,7 +74,7 @@ if not repositories: repo_list = Repository.query().all() else: - repo_names = [safe_unicode(n.strip()) for n in repositories] + repo_names = [n.strip() for n in repositories] repo_list = list(Repository.query() .filter(Repository.repo_name.in_(repo_names))) @@ -110,7 +110,7 @@ return parts = parts.groupdict() time_params = {} - for (name, param) in parts.iteritems(): + for name, param in parts.items(): if param: time_params[name] = int(param) return datetime.timedelta(**time_params) @@ -127,7 +127,7 @@ repos_location = Ui.get_repos_location() to_remove = [] - for dn_, dirs, f in os.walk(safe_str(repos_location)): + for dn_, dirs, f in os.walk(repos_location): alldirs = list(dirs) del dirs[:] if ('.hg' in alldirs or @@ -175,9 +175,8 @@ remove = True else: remove = ask_ok('The following repositories will be removed completely:\n%s\n' - 'Do you want to proceed? [y/n] ' - % '\n'.join(['%s deleted on %s' % (safe_str(x[0]), safe_str(x[1])) - for x in to_remove])) + 'Do you want to proceed? [y/n] ' % + '\n'.join('%s deleted on %s' % (path, date_) for path, date_ in to_remove)) if remove: for path, date_ in to_remove: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_cli_ssh.py --- a/kallithea/bin/kallithea_cli_ssh.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_cli_ssh.py Thu Feb 06 01:19:23 2020 +0100 @@ -14,7 +14,6 @@ import logging import os -import re import shlex import sys @@ -25,7 +24,7 @@ from kallithea.lib.utils2 import str2bool from kallithea.lib.vcs.backends.git.ssh import GitSshHandler from kallithea.lib.vcs.backends.hg.ssh import MercurialSshHandler -from kallithea.model.ssh_key import SshKeyModel +from kallithea.model.ssh_key import SshKeyModel, SshKeyModelException log = logging.getLogger(__name__) @@ -83,5 +82,8 @@ The file is usually maintained automatically, but this command will also re-write it. """ - - SshKeyModel().write_authorized_keys() + try: + SshKeyModel().write_authorized_keys() + except SshKeyModelException as e: + sys.stderr.write("%s\n" % e) + sys.exit(1) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/kallithea_gist.py --- a/kallithea/bin/kallithea_gist.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/kallithea_gist.py Thu Feb 06 01:19:23 2020 +0100 @@ -29,11 +29,12 @@ import argparse import fileinput +import json import os import stat import sys -from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call, json +from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call def argparser(argv): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/bin/ldap_sync.py --- a/kallithea/bin/ldap_sync.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/bin/ldap_sync.py Thu Feb 06 01:19:23 2020 +0100 @@ -27,13 +27,14 @@ from __future__ import print_function -import urllib2 +import urllib.request import uuid -from ConfigParser import ConfigParser +from configparser import ConfigParser import ldap -from kallithea.lib.compat import json +from kallithea.lib import ext_json +from kallithea.lib.utils2 import ascii_bytes config = ConfigParser() @@ -80,12 +81,12 @@ uid = str(uuid.uuid1()) data = self.get_api_data(uid, method, args) - data = json.dumps(data) + data = ascii_bytes(ext_json.dumps(data)) headers = {'content-type': 'text/plain'} - req = urllib2.Request(self.url, data, headers) + req = urllib.request.Request(self.url, data, headers) - response = urllib2.urlopen(req) - response = json.load(response) + response = urllib.request.urlopen(req) + response = ext_json.load(response) if uid != response["id"]: raise InvalidResponseIDError("UUID does not match.") diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/config/app_cfg.py --- a/kallithea/config/app_cfg.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/config/app_cfg.py Thu Feb 06 01:19:23 2020 +0100 @@ -28,20 +28,19 @@ from alembic.migration import MigrationContext from alembic.script.base import ScriptDirectory from sqlalchemy import create_engine -from tg import hooks from tg.configuration import AppConfig from tg.support.converters import asbool import kallithea.lib.locale import kallithea.model.base -from kallithea.lib.auth import set_available_permissions +import kallithea.model.meta from kallithea.lib.middleware.https_fixup import HttpsFixup from kallithea.lib.middleware.permanent_repo_url import PermanentRepoUrl from kallithea.lib.middleware.simplegit import SimpleGit from kallithea.lib.middleware.simplehg import SimpleHg from kallithea.lib.middleware.wrapper import RequestWrapper from kallithea.lib.utils import check_git_version, load_rcextensions, make_ui, set_app_settings, set_indexer_config, set_vcs_config -from kallithea.lib.utils2 import str2bool +from kallithea.lib.utils2 import safe_str, str2bool log = logging.getLogger(__name__) @@ -106,9 +105,6 @@ base_config = KallitheaAppConfig() -# TODO still needed as long as we use pylonslib -sys.modules['pylons'] = tg - # DebugBar, a debug toolbar for TurboGears2. # (https://github.com/TurboGears/tgext.debugbar) # To enable it, install 'tgext.debugbar' and 'kajiki', and run Kallithea with @@ -167,8 +163,7 @@ load_rcextensions(root_path=config['here']) - set_available_permissions(config) - repos_path = make_ui().configitems('paths')[0][1] + repos_path = safe_str(make_ui().configitems(b'paths')[0][1]) config['base_path'] = repos_path set_app_settings(config) @@ -188,8 +183,10 @@ check_git_version() + kallithea.model.meta.Session.remove() -hooks.register('configure_new_app', setup_configuration) + +tg.hooks.register('configure_new_app', setup_configuration) def setup_application(app): @@ -213,4 +210,4 @@ return app -hooks.register('before_config', setup_application) +tg.hooks.register('before_config', setup_application) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/config/conf.py --- a/kallithea/config/conf.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/config/conf.py Thu Feb 06 01:19:23 2020 +0100 @@ -35,7 +35,7 @@ # Whoosh index targets # Extensions we want to index content of using whoosh -INDEX_EXTENSIONS = LANGUAGES_EXTENSIONS_MAP.keys() +INDEX_EXTENSIONS = list(LANGUAGES_EXTENSIONS_MAP) # Filenames we want to index content of using whoosh INDEX_FILENAMES = pygmentsutils.get_index_filenames() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/config/middleware.py --- a/kallithea/config/middleware.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/config/middleware.py Thu Feb 06 01:19:23 2020 +0100 @@ -13,8 +13,6 @@ # along with this program. If not, see . """WSGI middleware initialization for the Kallithea application.""" -import logging.config - from kallithea.config.app_cfg import base_config from kallithea.config.environment import load_environment @@ -26,11 +24,6 @@ make_base_app = base_config.setup_tg_wsgi_app(load_environment) -def make_app_without_logging(global_conf, full_stack=True, **app_conf): - """The core of make_app for use from gearbox commands (other than 'serve')""" - return make_base_app(global_conf, full_stack=full_stack, **app_conf) - - def make_app(global_conf, full_stack=True, **app_conf): """ Set up Kallithea with the settings found in the PasteDeploy configuration @@ -49,5 +42,4 @@ ``app_conf`` contains all the application-specific settings (those defined under ``[app:main]``. """ - logging.config.fileConfig(global_conf['__file__']) - return make_app_without_logging(global_conf, full_stack=full_stack, **app_conf) + return make_base_app(global_conf, full_stack=full_stack, **app_conf) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/config/routing.py --- a/kallithea/config/routing.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/config/routing.py Thu Feb 06 01:19:23 2020 +0100 @@ -19,14 +19,34 @@ refer to the routes manual at http://routes.groovie.org/docs/ """ -from routes import Mapper +import routes from tg import request +from kallithea.lib.utils2 import safe_str + # prefix for non repository related links needs to be prefixed with `/` ADMIN_PREFIX = '/_admin' +class Mapper(routes.Mapper): + """ + Subclassed Mapper with routematch patched to decode "unicode" str url to + *real* unicode str before applying matches and invoking controller methods. + """ + + def routematch(self, url=None, environ=None): + """ + routematch that also decode url from "fake bytes" to real unicode + string before matching and invoking controllers. + """ + # Process url like get_path_info does ... but PATH_INFO has already + # been retrieved from environ and is passed, so - let's just use that + # instead. + url = safe_str(url.encode('latin1')) + return super().routematch(url=url, environ=environ) + + def make_map(config): """Create, configure and return the routes Mapper""" rmap = Mapper(directory=config['paths']['controllers'], @@ -86,7 +106,7 @@ #========================================================================== # MAIN PAGE - rmap.connect('home', '/', controller='home', action='index') + rmap.connect('home', '/', controller='home') rmap.connect('about', '/about', controller='home', action='about') rmap.redirect('/favicon.ico', '/images/favicon.ico') rmap.connect('repo_switcher_data', '/_repos', controller='home', @@ -106,7 +126,7 @@ m.connect("repos", "/repos", action="create", conditions=dict(method=["POST"])) m.connect("repos", "/repos", - action="index", conditions=dict(method=["GET"])) + conditions=dict(method=["GET"])) m.connect("new_repo", "/create_repository", action="create_repository", conditions=dict(method=["GET"])) m.connect("update_repo", "/repos/{repo_name:.*?}", @@ -121,7 +141,7 @@ m.connect("repos_groups", "/repo_groups", action="create", conditions=dict(method=["POST"])) m.connect("repos_groups", "/repo_groups", - action="index", conditions=dict(method=["GET"])) + conditions=dict(method=["GET"])) m.connect("new_repos_group", "/repo_groups/new", action="new", conditions=dict(method=["GET"])) m.connect("update_repos_group", "/repo_groups/{group_name:.*?}", @@ -161,9 +181,9 @@ m.connect("new_user", "/users/new", action="create", conditions=dict(method=["POST"])) m.connect("users", "/users", - action="index", conditions=dict(method=["GET"])) + conditions=dict(method=["GET"])) m.connect("formatted_users", "/users.{format}", - action="index", conditions=dict(method=["GET"])) + conditions=dict(method=["GET"])) m.connect("new_user", "/users/new", action="new", conditions=dict(method=["GET"])) m.connect("update_user", "/users/{id}", @@ -216,7 +236,7 @@ m.connect("users_groups", "/user_groups", action="create", conditions=dict(method=["POST"])) m.connect("users_groups", "/user_groups", - action="index", conditions=dict(method=["GET"])) + conditions=dict(method=["GET"])) m.connect("new_users_group", "/user_groups/new", action="new", conditions=dict(method=["GET"])) m.connect("update_users_group", "/user_groups/{id}", @@ -263,8 +283,7 @@ # ADMIN DEFAULTS ROUTES with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/defaults') as m: - m.connect('defaults', '/defaults', - action="index") + m.connect('defaults', '/defaults') m.connect('defaults_update', 'defaults/{id}/update', action="update", conditions=dict(method=["POST"])) @@ -370,7 +389,7 @@ m.connect("gists", "/gists", action="create", conditions=dict(method=["POST"])) m.connect("gists", "/gists", - action="index", conditions=dict(method=["GET"])) + conditions=dict(method=["GET"])) m.connect("new_gist", "/gists/new", action="new", conditions=dict(method=["GET"])) @@ -396,7 +415,7 @@ # ADMIN MAIN PAGES with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/admin') as m: - m.connect('admin_home', '', action='index') + m.connect('admin_home', '') m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9. _-]*}', action='add_repo') #========================================================================== @@ -408,7 +427,7 @@ # USER JOURNAL rmap.connect('journal', '%s/journal' % ADMIN_PREFIX, - controller='journal', action='index') + controller='journal') rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX, controller='journal', action='journal_rss') rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX, @@ -475,7 +494,7 @@ #========================================================================== rmap.connect('repo_creating_home', '/{repo_name:.*?}/repo_creating', controller='admin/repos', action='repo_creating') - rmap.connect('repo_check_home', '/{repo_name:.*?}/crepo_check', + rmap.connect('repo_check_home', '/{repo_name:.*?}/repo_check_creating', controller='admin/repos', action='repo_check') rmap.connect('summary_home', '/{repo_name:.*?}', @@ -602,7 +621,7 @@ rmap.connect('compare_home', '/{repo_name:.*?}/compare', - controller='compare', action='index', + controller='compare', conditions=dict(function=check_repo)) rmap.connect('compare_url', @@ -616,7 +635,7 @@ rmap.connect('pullrequest_home', '/{repo_name:.*?}/pull-request/new', controller='pullrequests', - action='index', conditions=dict(function=check_repo, + conditions=dict(function=check_repo, method=["GET"])) rmap.connect('pullrequest_repo_info', @@ -674,7 +693,7 @@ controller='changelog', conditions=dict(function=check_repo)) rmap.connect('changelog_file_home', '/{repo_name:.*?}/changelog/{revision}/{f_path:.*}', - controller='changelog', f_path=None, + controller='changelog', conditions=dict(function=check_repo)) rmap.connect('changelog_details', '/{repo_name:.*?}/changelog_details/{cs}', @@ -719,8 +738,8 @@ rmap.connect('files_annotate_home', '/{repo_name:.*?}/annotate/{revision}/{f_path:.*}', - controller='files', action='index', revision='tip', - f_path='', annotate=True, conditions=dict(function=check_repo)) + controller='files', revision='tip', + f_path='', annotate='1', conditions=dict(function=check_repo)) rmap.connect('files_edit_home', '/{repo_name:.*?}/edit/{revision}/{f_path:.*}', diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/admin.py --- a/kallithea/controllers/admin/admin.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/admin.py Thu Feb 06 01:19:23 2020 +0100 @@ -36,7 +36,6 @@ from whoosh.qparser.dateparse import DateParserPlugin from whoosh.qparser.default import QueryParser -from kallithea.config.routing import url from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired from kallithea.lib.base import BaseController, render from kallithea.lib.indexers import JOURNAL_SCHEMA @@ -61,7 +60,7 @@ if search_term: qp = QueryParser('repository', schema=JOURNAL_SCHEMA) qp.add_plugin(DateParserPlugin()) - qry = qp.parse(unicode(search_term)) + qry = qp.parse(search_term) log.debug('Filtering using parsed query %r', qry) def wildcard_handler(col, wc_term): @@ -139,10 +138,8 @@ p = safe_int(request.GET.get('page'), 1) - def url_generator(**kw): - return url.current(filter=c.search_term, **kw) - - c.users_log = Page(users_log, page=p, items_per_page=10, url=url_generator) + c.users_log = Page(users_log, page=p, items_per_page=10, + filter=c.search_term) if request.environ.get('HTTP_X_PARTIAL_XHR'): return render('admin/admin_log.html') diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/defaults.py --- a/kallithea/controllers/admin/defaults.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/defaults.py Thu Feb 06 01:19:23 2020 +0100 @@ -31,7 +31,6 @@ import formencode from formencode import htmlfill from tg import request -from tg import tmpl_context as c from tg.i18n import ugettext as _ from webob.exc import HTTPFound @@ -69,7 +68,7 @@ try: form_result = _form.to_python(dict(request.POST)) - for k, v in form_result.iteritems(): + for k, v in form_result.items(): setting = Setting.create_or_update(k, v) Session().commit() h.flash(_('Default settings updated successfully'), diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/gists.py --- a/kallithea/controllers/admin/gists.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/gists.py Thu Feb 06 01:19:23 2020 +0100 @@ -40,7 +40,7 @@ from kallithea.lib.auth import LoginRequired from kallithea.lib.base import BaseController, jsonify, render from kallithea.lib.page import Page -from kallithea.lib.utils2 import safe_int, safe_unicode, time_to_datetime +from kallithea.lib.utils2 import safe_int, safe_str, time_to_datetime from kallithea.lib.vcs.exceptions import NodeNotChangedError, VCSError from kallithea.model.db import Gist from kallithea.model.forms import GistForm @@ -71,6 +71,11 @@ not_default_user = not request.authuser.is_default_user c.show_private = request.GET.get('private') and not_default_user c.show_public = request.GET.get('public') and not_default_user + url_params = {} + if c.show_public: + url_params['public'] = 1 + elif c.show_private: + url_params['private'] = 1 gists = Gist().query() \ .filter_by(is_expired=False) \ @@ -97,7 +102,8 @@ c.gists = gists p = safe_int(request.GET.get('page'), 1) - c.gists_pager = Page(c.gists, page=p, items_per_page=10) + c.gists_pager = Page(c.gists, page=p, items_per_page=10, + **url_params) return render('admin/gists/index.html') @LoginRequired() @@ -176,7 +182,10 @@ log.error(traceback.format_exc()) raise HTTPNotFound() if format == 'raw': - content = '\n\n'.join([f.content for f in c.files if (f_path is None or safe_unicode(f.path) == f_path)]) + content = '\n\n'.join( + safe_str(f.content) + for f in c.files if (f_path is None or f.path == f_path) + ) response.content_type = 'text/plain' return content return render('admin/gists/show.html') diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/my_account.py --- a/kallithea/controllers/admin/my_account.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/my_account.py Thu Feb 06 01:19:23 2020 +0100 @@ -279,18 +279,18 @@ Session().commit() SshKeyModel().write_authorized_keys() h.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success') - except SshKeyModelException as errors: - h.flash(errors.message, category='error') + except SshKeyModelException as e: + h.flash(e.args[0], category='error') raise HTTPFound(location=url('my_account_ssh_keys')) @IfSshEnabled def my_account_ssh_keys_delete(self): - public_key = request.POST.get('del_public_key') + fingerprint = request.POST.get('del_public_key_fingerprint') try: - SshKeyModel().delete(public_key, request.authuser.user_id) + SshKeyModel().delete(fingerprint, request.authuser.user_id) Session().commit() SshKeyModel().write_authorized_keys() h.flash(_("SSH key successfully deleted"), category='success') - except SshKeyModelException as errors: - h.flash(errors.message, category='error') + except SshKeyModelException as e: + h.flash(e.args[0], category='error') raise HTTPFound(location=url('my_account_ssh_keys')) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/repo_groups.py --- a/kallithea/controllers/admin/repo_groups.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/repo_groups.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,7 +25,6 @@ :license: GPLv3, see LICENSE.md for more details. """ -import itertools import logging import traceback @@ -37,7 +36,6 @@ from tg.i18n import ungettext from webob.exc import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPNotFound -import kallithea from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoGroupPermissionLevelDecorator, LoginRequired @@ -93,10 +91,8 @@ return data def _revoke_perms_on_yourself(self, form_result): - _up = filter(lambda u: request.authuser.username == u[0], - form_result['perms_updates']) - _new = filter(lambda u: request.authuser.username == u[0], - form_result['perms_new']) + _up = [u for u in form_result['perms_updates'] if request.authuser.username == u[0]] + _new = [u for u in form_result['perms_new'] if request.authuser.username == u[0]] if _new and _new[0][1] != 'group.admin' or _up and _up[0][1] != 'group.admin': return True return False @@ -111,18 +107,16 @@ repo_group_name = lambda repo_group_name, children_groups: ( template.get_def("repo_group_name") - .render(repo_group_name, children_groups, _=_, h=h, c=c) + .render_unicode(repo_group_name, children_groups, _=_, h=h, c=c) ) repo_group_actions = lambda repo_group_id, repo_group_name, gr_count: ( template.get_def("repo_group_actions") - .render(repo_group_id, repo_group_name, gr_count, _=_, h=h, c=c, + .render_unicode(repo_group_id, repo_group_name, gr_count, _=_, h=h, c=c, ungettext=ungettext) ) for repo_gr in group_iter: - children_groups = map(h.safe_unicode, - itertools.chain((g.name for g in repo_gr.parents), - (x.name for x in [repo_gr]))) + children_groups = [g.name for g in repo_gr.parents] + [repo_gr.name] repo_count = repo_gr.repositories.count() repo_groups_data.append({ "raw_name": repo_gr.group_name, @@ -148,6 +142,7 @@ # permissions for can create group based on parent_id are checked # here in the Form repo_group_form = RepoGroupForm(repo_groups=c.repo_groups) + form_result = None try: form_result = repo_group_form.to_python(dict(request.POST)) gr = RepoGroupModel().create( @@ -171,6 +166,8 @@ log.error(traceback.format_exc()) h.flash(_('Error occurred during creation of repository group %s') % request.POST.get('group_name'), category='error') + if form_result is None: + raise parent_group_id = form_result['parent_group_id'] # TODO: maybe we should get back to the main view, not the admin one raise HTTPFound(location=url('repos_groups', parent_group=parent_group_id)) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/repos.py --- a/kallithea/controllers/admin/repos.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/repos.py Thu Feb 06 01:19:23 2020 +0100 @@ -471,7 +471,7 @@ category='success') except RepositoryError as e: log.error(traceback.format_exc()) - h.flash(str(e), category='error') + h.flash(e, category='error') except Exception as e: log.error(traceback.format_exc()) h.flash(_('An error occurred during this operation'), diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/settings.py --- a/kallithea/controllers/admin/settings.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/settings.py Thu Feb 06 01:19:23 2020 +0100 @@ -42,7 +42,7 @@ from kallithea.lib.celerylib import tasks from kallithea.lib.exceptions import HgsubversionImportError from kallithea.lib.utils import repo2db_mapper, set_app_settings -from kallithea.lib.utils2 import safe_unicode +from kallithea.lib.utils2 import safe_str from kallithea.lib.vcs import VCSError from kallithea.model.db import Repository, Setting, Ui from kallithea.model.forms import ApplicationSettingsForm, ApplicationUiSettingsForm, ApplicationVisualisationForm @@ -168,10 +168,10 @@ user=request.authuser.username, overwrite_git_hooks=overwrite_git_hooks) added_msg = h.HTML(', ').join( - h.link_to(safe_unicode(repo_name), h.url('summary_home', repo_name=repo_name)) for repo_name in added + h.link_to(safe_str(repo_name), h.url('summary_home', repo_name=repo_name)) for repo_name in added ) or '-' removed_msg = h.HTML(', ').join( - safe_unicode(repo_name) for repo_name in removed + safe_str(repo_name) for repo_name in removed ) or '-' h.flash(h.HTML(_('Repositories successfully rescanned. Added: %s. Removed: %s.')) % (added_msg, removed_msg), category='success') @@ -423,7 +423,7 @@ import kallithea c.ini = kallithea.CONFIG server_info = Setting.get_server_info() - for key, val in server_info.iteritems(): + for key, val in server_info.items(): setattr(c, key, val) return htmlfill.render( diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/user_groups.py --- a/kallithea/controllers/admin/user_groups.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/user_groups.py Thu Feb 06 01:19:23 2020 +0100 @@ -32,19 +32,18 @@ from formencode import htmlfill from sqlalchemy.orm import joinedload from sqlalchemy.sql.expression import func -from tg import app_globals, config, request +from tg import app_globals, request from tg import tmpl_context as c from tg.i18n import ugettext as _ from webob.exc import HTTPFound, HTTPInternalServerError -import kallithea from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.auth import HasPermissionAnyDecorator, HasUserGroupPermissionLevelDecorator, LoginRequired from kallithea.lib.base import BaseController, render from kallithea.lib.exceptions import RepoGroupAssignmentError, UserGroupsAssignedException from kallithea.lib.utils import action_logger -from kallithea.lib.utils2 import safe_int, safe_unicode +from kallithea.lib.utils2 import safe_int, safe_str from kallithea.model.db import User, UserGroup, UserGroupRepoGroupToPerm, UserGroupRepoToPerm, UserGroupToPerm from kallithea.model.forms import CustomDefaultPermissionsForm, UserGroupForm, UserGroupPermsForm from kallithea.model.meta import Session @@ -61,7 +60,6 @@ @LoginRequired(allow_default_user=True) def _before(self, *args, **kwargs): super(UserGroupsController, self)._before(*args, **kwargs) - c.available_permissions = config['available_permissions'] def __load_data(self, user_group_id): c.group_members_obj = sorted((x.user for x in c.user_group.members), @@ -94,11 +92,11 @@ user_group_name = lambda user_group_id, user_group_name: ( template.get_def("user_group_name") - .render(user_group_id, user_group_name, _=_, h=h, c=c) + .render_unicode(user_group_id, user_group_name, _=_, h=h, c=c) ) user_group_actions = lambda user_group_id, user_group_name: ( template.get_def("user_group_actions") - .render(user_group_id, user_group_name, _=_, h=h, c=c) + .render_unicode(user_group_id, user_group_name, _=_, h=h, c=c) ) for user_gr in group_iter: @@ -163,7 +161,7 @@ c.active = 'settings' self.__load_data(id) - available_members = [safe_unicode(x[0]) for x in c.available_members] + available_members = [safe_str(x[0]) for x in c.available_members] users_group_form = UserGroupForm(edit=True, old_data=c.user_group.get_dict(), diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/admin/users.py --- a/kallithea/controllers/admin/users.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/admin/users.py Thu Feb 06 01:19:23 2020 +0100 @@ -31,12 +31,11 @@ import formencode from formencode import htmlfill from sqlalchemy.sql.expression import func -from tg import app_globals, config, request +from tg import app_globals, request from tg import tmpl_context as c from tg.i18n import ugettext as _ from webob.exc import HTTPFound, HTTPNotFound -import kallithea from kallithea.config.routing import url from kallithea.lib import auth_modules from kallithea.lib import helpers as h @@ -63,7 +62,6 @@ @HasPermissionAnyDecorator('hg.admin') def _before(self, *args, **kwargs): super(UsersController, self)._before(*args, **kwargs) - c.available_permissions = config['available_permissions'] def index(self, format='html'): c.users_list = User.query().order_by(User.username) \ @@ -80,11 +78,11 @@ username = lambda user_id, username: ( template.get_def("user_name") - .render(user_id, username, _=_, h=h, c=c)) + .render_unicode(user_id, username, _=_, h=h, c=c)) user_actions = lambda user_id, username: ( template.get_def("user_actions") - .render(user_id, username, _=_, h=h, c=c)) + .render_unicode(user_id, username, _=_, h=h, c=c)) for user in c.users_list: users_data.append({ @@ -454,20 +452,20 @@ Session().commit() SshKeyModel().write_authorized_keys() h.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success') - except SshKeyModelException as errors: - h.flash(errors.message, category='error') + except SshKeyModelException as e: + h.flash(e.args[0], category='error') raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id)) @IfSshEnabled def ssh_keys_delete(self, id): c.user = self._get_user_or_raise_if_default(id) - public_key = request.POST.get('del_public_key') + fingerprint = request.POST.get('del_public_key_fingerprint') try: - SshKeyModel().delete(public_key, c.user.user_id) + SshKeyModel().delete(fingerprint, c.user.user_id) Session().commit() SshKeyModel().write_authorized_keys() h.flash(_("SSH key successfully deleted"), category='success') - except SshKeyModelException as errors: - h.flash(errors.message, category='error') + except SshKeyModelException as e: + h.flash(e.args[0], category='error') raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id)) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/api/__init__.py --- a/kallithea/controllers/api/__init__.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/api/__init__.py Thu Feb 06 01:19:23 2020 +0100 @@ -35,11 +35,11 @@ from tg import Response, TGController, request, response from webob.exc import HTTPError, HTTPException +from kallithea.lib import ext_json from kallithea.lib.auth import AuthUser -from kallithea.lib.base import _get_access_path from kallithea.lib.base import _get_ip_addr as _get_ip -from kallithea.lib.compat import json -from kallithea.lib.utils2 import safe_str, safe_unicode +from kallithea.lib.base import get_path_info +from kallithea.lib.utils2 import ascii_bytes from kallithea.model.db import User @@ -53,7 +53,7 @@ super(JSONRPCError, self).__init__() def __str__(self): - return safe_str(self.message) + return self.message class JSONRPCErrorResponse(Response, HTTPException): @@ -121,7 +121,7 @@ raw_body = environ['wsgi.input'].read(length) try: - json_body = json.loads(raw_body) + json_body = ext_json.loads(raw_body) except ValueError as e: # catch JSON errors Here raise JSONRPCErrorResponse(retid=self._req_id, @@ -166,13 +166,13 @@ # now that we have a method, add self._req_params to # self.kargs and dispatch control to WGIController - argspec = inspect.getargspec(self._func) - arglist = argspec[0][1:] - defaults = map(type, argspec[3] or []) - default_empty = types.NotImplementedType + argspec = inspect.getfullargspec(self._func) + arglist = argspec.args[1:] + argtypes = [type(arg) for arg in argspec.defaults or []] + default_empty = type(NotImplemented) # kw arguments required by this method - func_kwargs = dict(itertools.izip_longest(reversed(arglist), reversed(defaults), + func_kwargs = dict(itertools.zip_longest(reversed(arglist), reversed(argtypes), fillvalue=default_empty)) # This attribute will need to be first param of a method that uses @@ -180,7 +180,7 @@ USER_SESSION_ATTR = 'apiuser' # get our arglist and check if we provided them as args - for arg, default in func_kwargs.iteritems(): + for arg, default in func_kwargs.items(): if arg == USER_SESSION_ATTR: # USER_SESSION_ATTR is something translated from API key and # this is checked before so we don't need validate it @@ -209,7 +209,7 @@ log.info('IP: %s Request to %s time: %.3fs' % ( self._get_ip_addr(environ), - safe_unicode(_get_access_path(environ)), time.time() - start) + get_path_info(environ), time.time() - start) ) state.set_action(self._rpc_call, []) @@ -226,28 +226,28 @@ if isinstance(raw_response, HTTPError): self._error = str(raw_response) except JSONRPCError as e: - self._error = safe_str(e) + self._error = str(e) except Exception as e: log.error('Encountered unhandled exception: %s', traceback.format_exc(),) json_exc = JSONRPCError('Internal server error') - self._error = safe_str(json_exc) + self._error = str(json_exc) if self._error is not None: raw_response = None response = dict(id=self._req_id, result=raw_response, error=self._error) try: - return json.dumps(response) + return ascii_bytes(ext_json.dumps(response)) except TypeError as e: - log.error('API FAILED. Error encoding response: %s', e) - return json.dumps( + log.error('API FAILED. Error encoding response for %s %s: %s\n%s', action, rpc_args, e, traceback.format_exc()) + return ascii_bytes(ext_json.dumps( dict( id=self._req_id, result=None, - error="Error encoding response" + error="Error encoding response", ) - ) + )) def _find_method(self): """ diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/api/api.py --- a/kallithea/controllers/api/api.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/api/api.py Thu Feb 06 01:19:23 2020 +0100 @@ -1160,7 +1160,7 @@ return _map[ret_type] except KeyError: raise JSONRPCError('ret_type must be one of %s' - % (','.join(_map.keys()))) + % (','.join(sorted(_map)))) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( @@ -2339,7 +2339,7 @@ branch_name, reverse, max_revisions)] except EmptyRepositoryError as e: - raise JSONRPCError(e.message) + raise JSONRPCError('Repository is empty') # permission check inside def get_changeset(self, repoid, raw_id, with_reviews=Optional(False)): @@ -2400,7 +2400,7 @@ pull_request=pull_request.pull_request_id, f_path=None, line_no=None, - status_change=(ChangesetStatus.get_status_lbl(status)), + status_change=ChangesetStatus.get_status_lbl(status), closing_pr=close_pr ) action_logger(apiuser, diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/changelog.py --- a/kallithea/controllers/changelog.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/changelog.py Thu Feb 06 01:19:23 2020 +0100 @@ -38,8 +38,8 @@ from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired from kallithea.lib.base import BaseRepoController, render from kallithea.lib.graphmod import graph_data -from kallithea.lib.page import RepoPage -from kallithea.lib.utils2 import safe_int, safe_str +from kallithea.lib.page import Page +from kallithea.lib.utils2 import safe_int from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, ChangesetError, EmptyRepositoryError, NodeDoesNotExistError, RepositoryError @@ -67,7 +67,7 @@ h.flash(_('There are no changesets yet'), category='error') except RepositoryError as e: log.error(traceback.format_exc()) - h.flash(safe_str(e), category='error') + h.flash(e, category='error') raise HTTPBadRequest() @LoginRequired(allow_default_user=True) @@ -111,35 +111,34 @@ cs = self.__get_cs(revision, repo_name) collection = cs.get_file_history(f_path) except RepositoryError as e: - h.flash(safe_str(e), category='warning') + h.flash(e, category='warning') raise HTTPFound(location=h.url('changelog_home', repo_name=repo_name)) - collection = list(reversed(collection)) else: collection = c.db_repo_scm_instance.get_changesets(start=0, end=revision, - branch_name=branch_name) + branch_name=branch_name, reverse=True) c.total_cs = len(collection) - c.cs_pagination = RepoPage(collection, page=p, item_count=c.total_cs, - items_per_page=c.size, branch=branch_name,) + c.cs_pagination = Page(collection, page=p, item_count=c.total_cs, items_per_page=c.size, + branch=branch_name) page_revisions = [x.raw_id for x in c.cs_pagination] c.cs_comments = c.db_repo.get_comments(page_revisions) c.cs_statuses = c.db_repo.statuses(page_revisions) except EmptyRepositoryError as e: - h.flash(safe_str(e), category='warning') + h.flash(e, category='warning') raise HTTPFound(location=url('summary_home', repo_name=c.repo_name)) except (RepositoryError, ChangesetDoesNotExistError, Exception) as e: log.error(traceback.format_exc()) - h.flash(safe_str(e), category='error') + h.flash(e, category='error') raise HTTPFound(location=url('changelog_home', repo_name=c.repo_name)) c.branch_name = branch_name c.branch_filters = [('', _('None'))] + \ - [(k, k) for k in c.db_repo_scm_instance.branches.keys()] + [(k, k) for k in c.db_repo_scm_instance.branches] if c.db_repo_scm_instance.closed_branches: prefix = _('(closed)') + ' ' c.branch_filters += [('-', '-')] + \ - [(k, prefix + k) for k in c.db_repo_scm_instance.closed_branches.keys()] + [(k, prefix + k) for k in c.db_repo_scm_instance.closed_branches] revs = [] if not f_path: revs = [x.revision for x in c.cs_pagination] diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/changeset.py --- a/kallithea/controllers/changeset.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/changeset.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,6 +25,7 @@ :license: GPLv3, see LICENSE.md for more details. """ +import binascii import logging import traceback from collections import OrderedDict, defaultdict @@ -40,7 +41,7 @@ from kallithea.lib.base import BaseRepoController, jsonify, render from kallithea.lib.graphmod import graph_data from kallithea.lib.utils import action_logger -from kallithea.lib.utils2 import safe_unicode +from kallithea.lib.utils2 import ascii_str, safe_str from kallithea.lib.vcs.backends.base import EmptyChangeset from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError from kallithea.model.changeset_status import ChangesetStatusModel @@ -65,7 +66,7 @@ def get_ignore_ws(fid, GET): ig_ws_global = GET.get('ignorews') - ig_ws = filter(lambda k: k.startswith('WS'), GET.getall(fid)) + ig_ws = [k for k in GET.getall(fid) if k.startswith('WS')] if ig_ws: try: return int(ig_ws[0].split(':')[-1]) @@ -108,9 +109,9 @@ def get_line_ctx(fid, GET): ln_ctx_global = GET.get('context') if fid: - ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid)) + ln_ctx = [k for k in GET.getall(fid) if k.startswith('C')] else: - _ln_ctx = filter(lambda k: k.startswith('C'), GET) + _ln_ctx = [k for k in GET if k.startswith('C')] ln_ctx = GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global if ln_ctx: ln_ctx = [ln_ctx] @@ -256,7 +257,7 @@ Session().commit() data = { - 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), + 'target_id': h.safeid(request.POST.get('f_path')), } if comment is not None: c.comment = comment @@ -395,6 +396,8 @@ c.changeset = c.cs_ranges[0] c.parent_tmpl = ''.join(['# Parent %s\n' % x.raw_id for x in c.changeset.parents]) + c.changeset_graft_source_hash = ascii_str(c.changeset.extra.get(b'source', b'')) + c.changeset_transplant_source_hash = ascii_str(binascii.hexlify(c.changeset.extra.get(b'transplant_source', b''))) if method == 'download': response.content_type = 'text/plain' response.content_disposition = 'attachment; filename=%s.diff' \ @@ -402,7 +405,7 @@ return raw_diff elif method == 'patch': response.content_type = 'text/plain' - c.diff = safe_unicode(raw_diff) + c.diff = safe_str(raw_diff) return render('changeset/patch_changeset.html') elif method == 'raw': response.content_type = 'text/plain' diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/compare.py --- a/kallithea/controllers/compare.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/compare.py Thu Feb 06 01:19:23 2020 +0100 @@ -30,6 +30,7 @@ import logging import re +import mercurial.unionrepo from tg import request from tg import tmpl_context as c from tg.i18n import ugettext as _ @@ -42,8 +43,7 @@ from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired from kallithea.lib.base import BaseRepoController, render from kallithea.lib.graphmod import graph_data -from kallithea.lib.utils2 import safe_int, safe_str -from kallithea.lib.vcs.utils.hgcompat import unionrepo +from kallithea.lib.utils2 import ascii_bytes, ascii_str, safe_bytes, safe_int from kallithea.model.db import Repository @@ -97,14 +97,9 @@ elif alias == 'hg': # case two independent repos if org_repo != other_repo: - try: - hgrepo = unionrepo.makeunionrepository(other_repo.baseui, - other_repo.path, - org_repo.path) - except AttributeError: # makeunionrepository was introduced in Mercurial 4.8 23f2299e9e53 - hgrepo = unionrepo.unionrepository(other_repo.baseui, - other_repo.path, - org_repo.path) + hgrepo = mercurial.unionrepo.makeunionrepository(other_repo.baseui, + safe_bytes(other_repo.path), + safe_bytes(org_repo.path)) # all ancestors of other_rev will be in other_repo and # rev numbers from hgrepo can be used in other_repo - org_rev ancestors cannot @@ -112,21 +107,27 @@ else: hgrepo = other_repo._repo - ancestors = [hgrepo[ancestor].hex() for ancestor in - hgrepo.revs("id(%s) & ::id(%s)", other_rev, org_rev)] + ancestors = [ascii_str(hgrepo[ancestor].hex()) for ancestor in + hgrepo.revs(b"id(%s) & ::id(%s)", ascii_bytes(other_rev), ascii_bytes(org_rev))] if ancestors: log.debug("shortcut found: %s is already an ancestor of %s", other_rev, org_rev) else: log.debug("no shortcut found: %s is not an ancestor of %s", other_rev, org_rev) - ancestors = [hgrepo[ancestor].hex() for ancestor in - hgrepo.revs("heads(::id(%s) & ::id(%s))", org_rev, other_rev)] # FIXME: expensive! + ancestors = [ascii_str(hgrepo[ancestor].hex()) for ancestor in + hgrepo.revs(b"heads(::id(%s) & ::id(%s))", ascii_bytes(org_rev), ascii_bytes(other_rev))] # FIXME: expensive! - other_revs = hgrepo.revs("ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)", - other_rev, org_rev, org_rev) - other_changesets = [other_repo.get_changeset(rev) for rev in other_revs] - org_revs = hgrepo.revs("ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)", - org_rev, other_rev, other_rev) - org_changesets = [org_repo.get_changeset(hgrepo[rev].hex()) for rev in org_revs] + other_changesets = [ + other_repo.get_changeset(rev) + for rev in hgrepo.revs( + b"ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)", + ascii_bytes(other_rev), ascii_bytes(org_rev), ascii_bytes(org_rev)) + ] + org_changesets = [ + org_repo.get_changeset(ascii_str(hgrepo[rev].hex())) + for rev in hgrepo.revs( + b"ancestors(id(%s)) and not ancestors(id(%s)) and not id(%s)", + ascii_bytes(org_rev), ascii_bytes(other_rev), ascii_bytes(other_rev)) + ] elif alias == 'git': if org_repo != other_repo: @@ -134,15 +135,15 @@ from dulwich.client import SubprocessGitClient gitrepo = Repo(org_repo.path) - SubprocessGitClient(thin_packs=False).fetch(safe_str(other_repo.path), gitrepo) + SubprocessGitClient(thin_packs=False).fetch(other_repo.path, gitrepo) gitrepo_remote = Repo(other_repo.path) - SubprocessGitClient(thin_packs=False).fetch(safe_str(org_repo.path), gitrepo_remote) + SubprocessGitClient(thin_packs=False).fetch(org_repo.path, gitrepo_remote) revs = [ - x.commit.id - for x in gitrepo_remote.get_walker(include=[other_rev], - exclude=[org_rev]) + ascii_str(x.commit.id) + for x in gitrepo_remote.get_walker(include=[ascii_bytes(other_rev)], + exclude=[ascii_bytes(org_rev)]) ] other_changesets = [other_repo.get_changeset(rev) for rev in reversed(revs)] if other_changesets: @@ -155,13 +156,13 @@ gitrepo_remote.close() else: - so, se = org_repo.run_git_command( + so = org_repo.run_git_command( ['log', '--reverse', '--pretty=format:%H', '-s', '%s..%s' % (org_rev, other_rev)] ) other_changesets = [org_repo.get_changeset(cs) for cs in re.findall(r'[0-9a-fA-F]{40}', so)] - so, se = org_repo.run_git_command( + so = org_repo.run_git_command( ['merge-base', org_rev, other_rev] ) ancestors = [re.findall(r'[0-9a-fA-F]{40}', so)[0]] @@ -277,7 +278,7 @@ ignore_whitespace=ignore_whitespace, context=line_context) - diff_processor = diffs.DiffProcessor(raw_diff or '', diff_limit=diff_limit) + diff_processor = diffs.DiffProcessor(raw_diff, diff_limit=diff_limit) c.limited_diff = diff_processor.limited_diff c.file_diff_data = [] c.lines_added = 0 diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/error.py --- a/kallithea/controllers/error.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/error.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,7 +25,7 @@ :license: GPLv3, see LICENSE.md for more details. """ -import cgi +import html import logging from tg import config, expose, request @@ -64,8 +64,7 @@ '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_message = html.escape(request.GET.get('code', str(resp.status))) c.error_explanation = self.get_error_explanation(resp.status_int) else: c.error_message = _('No response') diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/feed.py --- a/kallithea/controllers/feed.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/feed.py Thu Feb 06 01:19:23 2020 +0100 @@ -32,23 +32,19 @@ from tg import response from tg import tmpl_context as c from tg.i18n import ugettext as _ -from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed from kallithea import CONFIG +from kallithea.lib import feeds from kallithea.lib import helpers as h from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired from kallithea.lib.base import BaseRepoController from kallithea.lib.diffs import DiffProcessor -from kallithea.lib.utils2 import safe_int, safe_unicode, str2bool +from kallithea.lib.utils2 import safe_int, safe_str, str2bool log = logging.getLogger(__name__) -language = 'en-us' -ttl = "5" - - class FeedController(BaseRepoController): @LoginRequired(allow_default_user=True) @@ -98,64 +94,41 @@ desc_msg.extend(changes) if str2bool(CONFIG.get('rss_include_diff', False)): desc_msg.append('\n\n') - desc_msg.append(raw_diff) + desc_msg.append(safe_str(raw_diff)) desc_msg.append('') - return map(safe_unicode, desc_msg) + return desc_msg - def atom(self, repo_name): - """Produce an atom-1.0 feed via feedgenerator module""" + def _feed(self, repo_name, feeder): + """Produce a simple feed""" @cache_region('long_term', '_get_feed_from_cache') def _get_feed_from_cache(*_cache_keys): # parameters are not really used - only as caching key - feed = Atom1Feed( + header = dict( title=_('%s %s feed') % (c.site_name, repo_name), link=h.canonical_url('summary_home', repo_name=repo_name), description=_('Changes on %s repository') % repo_name, - language=language, - ttl=ttl ) rss_items_per_page = safe_int(CONFIG.get('rss_items_per_page', 20)) + entries=[] for cs in reversed(list(c.db_repo_scm_instance[-rss_items_per_page:])): - feed.add_item(title=self._get_title(cs), - link=h.canonical_url('changeset_home', repo_name=repo_name, - revision=cs.raw_id), - author_name=cs.author, - description=''.join(self.__get_desc(cs)), - pubdate=cs.date, - ) + entries.append(dict( + title=self._get_title(cs), + link=h.canonical_url('changeset_home', repo_name=repo_name, revision=cs.raw_id), + author_email=cs.author_email, + author_name=cs.author_name, + description=''.join(self.__get_desc(cs)), + pubdate=cs.date, + )) + return feeder.render(header, entries) - response.content_type = feed.mime_type - return feed.writeString('utf-8') + response.content_type = feeder.content_type + return _get_feed_from_cache(repo_name, feeder.__name__) - kind = 'ATOM' - return _get_feed_from_cache(repo_name, kind, c.db_repo.changeset_cache.get('raw_id')) + def atom(self, repo_name): + """Produce a simple atom-1.0 feed""" + return self._feed(repo_name, feeds.AtomFeed) def rss(self, repo_name): - """Produce an rss2 feed via feedgenerator module""" - - @cache_region('long_term', '_get_feed_from_cache') - def _get_feed_from_cache(*_cache_keys): # parameters are not really used - only as caching key - feed = Rss201rev2Feed( - title=_('%s %s feed') % (c.site_name, repo_name), - link=h.canonical_url('summary_home', repo_name=repo_name), - description=_('Changes on %s repository') % repo_name, - language=language, - ttl=ttl - ) - - rss_items_per_page = safe_int(CONFIG.get('rss_items_per_page', 20)) - for cs in reversed(list(c.db_repo_scm_instance[-rss_items_per_page:])): - feed.add_item(title=self._get_title(cs), - link=h.canonical_url('changeset_home', repo_name=repo_name, - revision=cs.raw_id), - author_name=cs.author, - description=''.join(self.__get_desc(cs)), - pubdate=cs.date, - ) - - response.content_type = feed.mime_type - return feed.writeString('utf-8') - - kind = 'RSS' - return _get_feed_from_cache(repo_name, kind, c.db_repo.changeset_cache.get('raw_id')) + """Produce a simple rss2 feed""" + return self._feed(repo_name, feeds.RssFeed) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/files.py --- a/kallithea/controllers/files.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/files.py Thu Feb 06 01:19:23 2020 +0100 @@ -90,7 +90,7 @@ h.flash(msg, category='error') raise HTTPNotFound() except RepositoryError as e: - h.flash(safe_str(e), category='error') + h.flash(e, category='error') raise HTTPNotFound() def __get_filenode(self, cs, path): @@ -110,7 +110,7 @@ h.flash(msg, category='error') raise HTTPNotFound() except RepositoryError as e: - h.flash(safe_str(e), category='error') + h.flash(e, category='error') raise HTTPNotFound() return file_node @@ -163,7 +163,7 @@ c.load_full_history = False # determine if we're on branch head _branches = c.db_repo_scm_instance.branches - c.on_branch_head = revision in _branches.keys() + _branches.values() + c.on_branch_head = revision in _branches or revision in _branches.values() _hist = [] c.file_history = [] if c.load_full_history: @@ -175,7 +175,7 @@ else: c.authors = c.file_history = [] except RepositoryError as e: - h.flash(safe_str(e), category='error') + h.flash(e, category='error') raise HTTPNotFound() if request.environ.get('HTTP_X_PARTIAL_XHR'): @@ -232,8 +232,8 @@ cs = self.__get_cs(revision) file_node = self.__get_filenode(cs, f_path) - response.content_disposition = 'attachment; filename=%s' % \ - safe_str(f_path.split(Repository.url_sep())[-1]) + response.content_disposition = \ + 'attachment; filename=%s' % f_path.split(Repository.url_sep())[-1] response.content_type = file_node.mimetype return file_node.content @@ -277,8 +277,7 @@ mimetype, dispo = 'text/plain', 'inline' if dispo == 'attachment': - dispo = 'attachment; filename=%s' % \ - safe_str(f_path.split(os.sep)[-1]) + dispo = 'attachment; filename=%s' % f_path.split(os.sep)[-1] response.content_disposition = dispo response.content_type = mimetype @@ -292,7 +291,7 @@ # create multiple heads via file editing _branches = repo.scm_instance.branches # check if revision is a branch name or branch hash - if revision not in _branches.keys() + _branches.values(): + if revision not in _branches and revision not in _branches.values(): h.flash(_('You can only delete files with revision ' 'being a valid branch'), category='warning') raise HTTPFound(location=h.url('files_home', @@ -346,7 +345,7 @@ # create multiple heads via file editing _branches = repo.scm_instance.branches # check if revision is a branch name or branch hash - if revision not in _branches.keys() + _branches.values(): + if revision not in _branches and revision not in _branches.values(): h.flash(_('You can only edit files with revision ' 'being a valid branch'), category='warning') raise HTTPFound(location=h.url('files_home', @@ -365,8 +364,7 @@ c.f_path = f_path if r_post: - - old_content = c.file.content + old_content = safe_str(c.file.content) sl = old_content.splitlines(1) first_line = sl[0] if sl else '' # modes: 0 - Unix, 1 - Mac, 2 - DOS @@ -509,8 +507,7 @@ from kallithea import CONFIG rev_name = cs.raw_id[:12] - archive_name = '%s-%s%s' % (safe_str(repo_name.replace('/', '_')), - safe_str(rev_name), ext) + archive_name = '%s-%s%s' % (repo_name.replace('/', '_'), rev_name, ext) archive_path = None cached_archive_path = None diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/home.py --- a/kallithea/controllers/home.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/home.py Thu Feb 06 01:19:23 2020 +0100 @@ -37,7 +37,7 @@ from kallithea.lib import helpers as h from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired from kallithea.lib.base import BaseController, jsonify, render -from kallithea.lib.utils import conditional_cache +from kallithea.lib.utils2 import safe_str from kallithea.model.db import RepoGroup, Repository, User, UserGroup from kallithea.model.repo import RepoModel from kallithea.model.scm import UserGroupList @@ -67,9 +67,7 @@ @LoginRequired(allow_default_user=True) @jsonify def repo_switcher_data(self): - # wrapper for conditional cache - def _c(): - log.debug('generating switcher repo/groups list') + if request.is_xhr: all_repos = Repository.query(sorted=True).all() repo_iter = self.scm_model.get_repos(all_repos) all_groups = RepoGroup.query(sorted=True).all() @@ -96,17 +94,16 @@ ], }] + for res_dict in res: + for child in (res_dict['children']): + child['obj'].pop('_changeset_cache', None) # bytes cannot be encoded in json ... but this value isn't relevant on client side at all ... + data = { 'more': False, 'results': res, } return data - if request.is_xhr: - condition = False - compute = conditional_cache('short_term', 'cache_desc', - condition=condition, func=_c) - return compute() else: raise HTTPBadRequest() @@ -120,25 +117,25 @@ if _branches: res.append({ 'text': _('Branch'), - 'children': [{'id': rev, 'text': name, 'type': 'branch'} for name, rev in _branches] + 'children': [{'id': safe_str(rev), 'text': safe_str(name), 'type': 'branch'} for name, rev in _branches] }) _closed_branches = repo.closed_branches.items() if _closed_branches: res.append({ 'text': _('Closed Branches'), - 'children': [{'id': rev, 'text': name, 'type': 'closed-branch'} for name, rev in _closed_branches] + 'children': [{'id': safe_str(rev), 'text': safe_str(name), 'type': 'closed-branch'} for name, rev in _closed_branches] }) _tags = repo.tags.items() if _tags: res.append({ 'text': _('Tag'), - 'children': [{'id': rev, 'text': name, 'type': 'tag'} for name, rev in _tags] + 'children': [{'id': safe_str(rev), 'text': safe_str(name), 'type': 'tag'} for name, rev in _tags] }) _bookmarks = repo.bookmarks.items() if _bookmarks: res.append({ 'text': _('Bookmark'), - 'children': [{'id': rev, 'text': name, 'type': 'book'} for name, rev in _bookmarks] + 'children': [{'id': safe_str(rev), 'text': safe_str(name), 'type': 'book'} for name, rev in _bookmarks] }) data = { 'more': False, diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/journal.py --- a/kallithea/controllers/journal.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/journal.py Thu Feb 06 01:19:23 2020 +0100 @@ -23,7 +23,6 @@ :author: marcink :copyright: (c) 2013 RhodeCode GmbH, and others. :license: GPLv3, see LICENSE.md for more details. - """ import logging @@ -35,12 +34,11 @@ from tg import request, response from tg import tmpl_context as c from tg.i18n import ugettext as _ -from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed from webob.exc import HTTPBadRequest import kallithea.lib.helpers as h -from kallithea.config.routing import url from kallithea.controllers.admin.admin import _journal_filter +from kallithea.lib import feeds from kallithea.lib.auth import LoginRequired from kallithea.lib.base import BaseController, render from kallithea.lib.page import Page @@ -105,22 +103,17 @@ return journal - def _atom_feed(self, repos, public=True): + def _feed(self, repos, feeder, link, desc): + response.content_type = feeder.content_type journal = self._get_journal_data(repos) - if public: - _link = h.canonical_url('public_journal_atom') - _desc = '%s %s %s' % (c.site_name, _('Public Journal'), - 'atom feed') - else: - _link = h.canonical_url('journal_atom') - _desc = '%s %s %s' % (c.site_name, _('Journal'), 'atom feed') - feed = Atom1Feed(title=_desc, - link=_link, - description=_desc, - language=language, - ttl=ttl) + header = dict( + title=desc, + link=link, + description=desc, + ) + entries=[] for entry in journal[:feed_nr]: user = entry.user if user is None: @@ -131,63 +124,43 @@ action, action_extra, ico = h.action_parser(entry, feed=True) title = "%s - %s %s" % (user.short_contact, action(), entry.repository.repo_name) - desc = action_extra() _url = None if entry.repository is not None: _url = h.canonical_url('changelog_home', repo_name=entry.repository.repo_name) - feed.add_item(title=title, - pubdate=entry.action_date, - link=_url or h.canonical_url(''), - author_email=user.email, - author_name=user.full_contact, - description=desc) + entries.append(dict( + title=title, + pubdate=entry.action_date, + link=_url or h.canonical_url(''), + author_email=user.email, + author_name=user.full_name_or_username, + description=action_extra(), + )) + + return feeder.render(header, entries) - response.content_type = feed.mime_type - return feed.writeString('utf-8') + def _atom_feed(self, repos, public=True): + if public: + link = h.canonical_url('public_journal_atom') + desc = '%s %s %s' % (c.site_name, _('Public Journal'), + 'atom feed') + else: + link = h.canonical_url('journal_atom') + desc = '%s %s %s' % (c.site_name, _('Journal'), 'atom feed') + + return self._feed(repos, feeds.AtomFeed, link, desc) def _rss_feed(self, repos, public=True): - journal = self._get_journal_data(repos) if public: - _link = h.canonical_url('public_journal_atom') - _desc = '%s %s %s' % (c.site_name, _('Public Journal'), + link = h.canonical_url('public_journal_atom') + desc = '%s %s %s' % (c.site_name, _('Public Journal'), 'rss feed') else: - _link = h.canonical_url('journal_atom') - _desc = '%s %s %s' % (c.site_name, _('Journal'), 'rss feed') - - feed = Rss201rev2Feed(title=_desc, - link=_link, - description=_desc, - language=language, - ttl=ttl) + link = h.canonical_url('journal_atom') + desc = '%s %s %s' % (c.site_name, _('Journal'), 'rss feed') - for entry in journal[:feed_nr]: - user = entry.user - if user is None: - # fix deleted users - user = AttributeDict({'short_contact': entry.username, - 'email': '', - 'full_contact': ''}) - action, action_extra, ico = h.action_parser(entry, feed=True) - title = "%s - %s %s" % (user.short_contact, action(), - entry.repository.repo_name) - desc = action_extra() - _url = None - if entry.repository is not None: - _url = h.canonical_url('changelog_home', - repo_name=entry.repository.repo_name) - - feed.add_item(title=title, - pubdate=entry.action_date, - link=_url or h.canonical_url(''), - author_email=user.email, - author_name=user.full_contact, - description=desc) - - response.content_type = feed.mime_type - return feed.writeString('utf-8') + return self._feed(repos, feeds.RssFeed, link, desc) @LoginRequired() def index(self): @@ -201,10 +174,8 @@ journal = self._get_journal_data(c.following) - def url_generator(**kw): - return url.current(filter=c.search_term, **kw) - - c.journal_pager = Page(journal, page=p, items_per_page=20, url=url_generator) + c.journal_pager = Page(journal, page=p, items_per_page=20, + filter=c.search_term) c.journal_day_aggregate = self._get_daily_aggregate(c.journal_pager) if request.environ.get('HTTP_X_PARTIAL_XHR'): @@ -221,9 +192,7 @@ @LoginRequired() def journal_atom(self): - """ - Produce an atom-1.0 feed via feedgenerator module - """ + """Produce a simple atom-1.0 feed""" following = UserFollowing.query() \ .filter(UserFollowing.user_id == request.authuser.user_id) \ .options(joinedload(UserFollowing.follows_repository)) \ @@ -232,9 +201,7 @@ @LoginRequired() def journal_rss(self): - """ - Produce an rss feed via feedgenerator module - """ + """Produce a simple rss2 feed""" following = UserFollowing.query() \ .filter(UserFollowing.user_id == request.authuser.user_id) \ .options(joinedload(UserFollowing.follows_repository)) \ @@ -290,9 +257,7 @@ @LoginRequired(allow_default_user=True) def public_journal_atom(self): - """ - Produce an atom-1.0 feed via feedgenerator module - """ + """Produce a simple atom-1.0 feed""" c.following = UserFollowing.query() \ .filter(UserFollowing.user_id == request.authuser.user_id) \ .options(joinedload(UserFollowing.follows_repository)) \ @@ -302,9 +267,7 @@ @LoginRequired(allow_default_user=True) def public_journal_rss(self): - """ - Produce an rss2 feed via feedgenerator module - """ + """Produce a simple rss2 feed""" c.following = UserFollowing.query() \ .filter(UserFollowing.user_id == request.authuser.user_id) \ .options(joinedload(UserFollowing.follows_repository)) \ diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/login.py --- a/kallithea/controllers/login.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/login.py Thu Feb 06 01:19:23 2020 +0100 @@ -41,7 +41,6 @@ from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator from kallithea.lib.base import BaseController, log_in_user, render from kallithea.lib.exceptions import UserCreationError -from kallithea.lib.utils2 import safe_str from kallithea.model.db import Setting, User from kallithea.model.forms import LoginForm, PasswordResetConfirmationForm, PasswordResetRequestForm, RegisterForm from kallithea.model.meta import Session @@ -68,7 +67,7 @@ return _re.match(came_from) is not None def index(self): - c.came_from = safe_str(request.GET.get('came_from', '')) + c.came_from = request.GET.get('came_from', '') if c.came_from: if not self._validate_came_from(c.came_from): log.error('Invalid came_from (not server-relative): %r', c.came_from) @@ -210,12 +209,10 @@ # The template needs the email address outside of the form. c.email = request.params.get('email') - + c.timestamp = request.params.get('timestamp') or '' + c.token = request.params.get('token') or '' if not request.POST: - return htmlfill.render( - render('/password_reset_confirmation.html'), - defaults=dict(request.params), - encoding='UTF-8') + return render('/password_reset_confirmation.html') form = PasswordResetConfirmationForm()() try: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/pullrequests.py --- a/kallithea/controllers/pullrequests.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/pullrequests.py Thu Feb 06 01:19:23 2020 +0100 @@ -29,6 +29,7 @@ import traceback import formencode +import mercurial.unionrepo from tg import request from tg import tmpl_context as c from tg.i18n import ugettext as _ @@ -42,10 +43,8 @@ from kallithea.lib.base import BaseRepoController, jsonify, render from kallithea.lib.graphmod import graph_data from kallithea.lib.page import Page -from kallithea.lib.utils2 import safe_int +from kallithea.lib.utils2 import ascii_bytes, safe_bytes, safe_int from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, EmptyRepositoryError -from kallithea.lib.vcs.utils import safe_str -from kallithea.lib.vcs.utils.hgcompat import unionrepo from kallithea.model.changeset_status import ChangesetStatusModel from kallithea.model.comment import ChangesetCommentsModel from kallithea.model.db import ChangesetStatus, PullRequest, PullRequestReviewer, Repository, User @@ -83,22 +82,15 @@ # list named branches that has been merged to this named branch - it should probably merge back peers = [] - if rev: - rev = safe_str(rev) - - if branch: - branch = safe_str(branch) - if branch_rev: - branch_rev = safe_str(branch_rev) # a revset not restricting to merge() would be better # (especially because it would get the branch point) # ... but is currently too expensive # including branches of children could be nice too peerbranches = set() for i in repo._repo.revs( - "sort(parents(branch(id(%s)) and merge()) - branch(id(%s)), -rev)", - branch_rev, branch_rev + b"sort(parents(branch(id(%s)) and merge()) - branch(id(%s)), -rev)", + ascii_bytes(branch_rev), ascii_bytes(branch_rev), ): for abranch in repo.get_changeset(i).branches: if abranch not in peerbranches: @@ -111,7 +103,7 @@ tipbranch = None branches = [] - for abranch, branchrev in repo.branches.iteritems(): + for abranch, branchrev in repo.branches.items(): n = 'branch:%s:%s' % (abranch, branchrev) desc = abranch if branchrev == tiprev: @@ -135,14 +127,14 @@ log.debug('branch %r not found in %s', branch, repo) bookmarks = [] - for bookmark, bookmarkrev in repo.bookmarks.iteritems(): + for bookmark, bookmarkrev in repo.bookmarks.items(): n = 'book:%s:%s' % (bookmark, bookmarkrev) bookmarks.append((n, bookmark)) if rev == bookmarkrev: selected = n tags = [] - for tag, tagrev in repo.tags.iteritems(): + for tag, tagrev in repo.tags.items(): if tag == 'tip': continue n = 'tag:%s:%s' % (tag, tagrev) @@ -173,7 +165,7 @@ if 'master' in repo.branches: selected = 'branch:master:%s' % repo.branches['master'] else: - k, v = repo.branches.items()[0] + k, v = list(repo.branches.items())[0] selected = 'branch:%s:%s' % (k, v) groups = [(specials, _("Special")), @@ -201,6 +193,11 @@ def show_all(self, repo_name): c.from_ = request.GET.get('from_') or '' c.closed = request.GET.get('closed') or '' + url_params = {} + if c.from_: + url_params['from_'] = 1 + if c.closed: + url_params['closed'] = 1 p = safe_int(request.GET.get('page'), 1) q = PullRequest.query(include_closed=c.closed, sorted=True) @@ -210,7 +207,7 @@ q = q.filter_by(other_repo=c.db_repo) c.pull_requests = q.all() - c.pullrequests_pager = Page(c.pull_requests, page=p, items_per_page=100) + c.pullrequests_pager = Page(c.pull_requests, page=p, items_per_page=100, **url_params) return render('/pullrequests/pullrequest_show_all.html') @@ -335,7 +332,7 @@ try: cmd = CreatePullRequestAction(org_repo, other_repo, org_ref, other_ref, title, description, owner, reviewers) except CreatePullRequestAction.ValidationError as e: - h.flash(str(e), category='error', logf=log.error) + h.flash(e, category='error', logf=log.error) raise HTTPNotFound try: @@ -358,7 +355,7 @@ try: cmd = CreatePullRequestIterationAction(old_pull_request, new_org_rev, new_other_rev, title, description, owner, reviewers) except CreatePullRequestAction.ValidationError as e: - h.flash(str(e), category='error', logf=log.error) + h.flash(e, category='error', logf=log.error) raise HTTPNotFound try: @@ -470,14 +467,15 @@ c.a_rev) = c.pull_request.other_ref.split(':') # a_rev is ancestor org_scm_instance = c.cs_repo.scm_instance # property with expensive cache invalidation check!!! - try: - c.cs_ranges = [] - for x in c.pull_request.revisions: + c.cs_ranges = [] + for x in c.pull_request.revisions: + try: c.cs_ranges.append(org_scm_instance.get_changeset(x)) - except ChangesetDoesNotExistError: - c.cs_ranges = [] - h.flash(_('Revision %s not found in %s') % (x, c.cs_repo.repo_name), - 'error') + except ChangesetDoesNotExistError: + c.cs_ranges = [] + h.flash(_('Revision %s not found in %s') % (x, c.cs_repo.repo_name), + 'error') + break c.cs_ranges_org = None # not stored and not important and moving target - could be calculated ... revs = [ctx.revision for ctx in reversed(c.cs_ranges)] c.jsdata = graph_data(org_scm_instance, revs) @@ -530,14 +528,9 @@ # Note: org_scm_instance.path must come first so all # valid revision numbers are 100% org_scm compatible # - both for avail_revs and for revset results - try: - hgrepo = unionrepo.makeunionrepository(org_scm_instance.baseui, - org_scm_instance.path, - other_scm_instance.path) - except AttributeError: # makeunionrepository was introduced in Mercurial 4.8 23f2299e9e53 - hgrepo = unionrepo.unionrepository(org_scm_instance.baseui, - org_scm_instance.path, - other_scm_instance.path) + hgrepo = mercurial.unionrepo.makeunionrepository(org_scm_instance.baseui, + safe_bytes(org_scm_instance.path), + safe_bytes(other_scm_instance.path)) else: hgrepo = org_scm_instance._repo show = set(hgrepo.revs('::%ld & !::parents(%s) & !::%s', @@ -587,11 +580,11 @@ log.debug('running diff between %s and %s in %s', c.a_rev, c.cs_rev, org_scm_instance.path) try: - raw_diff = diffs.get_diff(org_scm_instance, rev1=safe_str(c.a_rev), rev2=safe_str(c.cs_rev), + raw_diff = diffs.get_diff(org_scm_instance, rev1=c.a_rev, rev2=c.cs_rev, ignore_whitespace=ignore_whitespace, context=line_context) except ChangesetDoesNotExistError: - raw_diff = _("The diff can't be shown - the PR revisions could not be found.") - diff_processor = diffs.DiffProcessor(raw_diff or '', diff_limit=diff_limit) + raw_diff = safe_bytes(_("The diff can't be shown - the PR revisions could not be found.")) + diff_processor = diffs.DiffProcessor(raw_diff, diff_limit=diff_limit) c.limited_diff = diff_processor.limited_diff c.file_diff_data = [] c.lines_added = 0 diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/search.py --- a/kallithea/controllers/search.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/search.py Thu Feb 06 01:19:23 2020 +0100 @@ -27,12 +27,10 @@ import logging import traceback -import urllib from tg import config, request from tg import tmpl_context as c from tg.i18n import ugettext as _ -from webhelpers2.html.tools import update_params from whoosh.index import EmptyIndexError, exists_in, open_dir from whoosh.qparser import QueryParser, QueryParserError from whoosh.query import Phrase, Prefix @@ -41,7 +39,7 @@ from kallithea.lib.base import BaseRepoController, render from kallithea.lib.indexers import CHGSET_IDX_NAME, CHGSETS_SCHEMA, IDX_NAME, SCHEMA, WhooshResultWrapper from kallithea.lib.page import Page -from kallithea.lib.utils2 import safe_int, safe_str +from kallithea.lib.utils2 import safe_int from kallithea.model.repo import RepoModel @@ -98,7 +96,7 @@ # for case-sensitive matching cur_query = u'repository_rawname:%s %s' % (c.repo_name, cur_query) try: - query = qp.parse(unicode(cur_query)) + query = qp.parse(cur_query) # extract words for highlight if isinstance(query, Phrase): highlight_items.update(query.words) @@ -119,9 +117,6 @@ res_ln, results.runtime ) - def url_generator(**kw): - q = urllib.quote(safe_str(c.cur_query)) - return update_params("?q=%s&type=%s" % (q, safe_str(c.cur_type)), **kw) repo_location = RepoModel().repos_path c.formated_results = Page( WhooshResultWrapper(search_type, searcher, matcher, @@ -129,7 +124,8 @@ page=p, item_count=res_ln, items_per_page=10, - url=url_generator + type=c.cur_type, + q=c.cur_query, ) except QueryParserError: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/controllers/summary.py --- a/kallithea/controllers/summary.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/controllers/summary.py Thu Feb 06 01:19:23 2020 +0100 @@ -38,14 +38,15 @@ from tg.i18n import ugettext as _ from webob.exc import HTTPBadRequest +import kallithea.lib.helpers as h from kallithea.config.conf import ALL_EXTS, ALL_READMES, LANGUAGES_EXTENSIONS_MAP +from kallithea.lib import ext_json from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired from kallithea.lib.base import BaseRepoController, jsonify, render from kallithea.lib.celerylib.tasks import get_commits_stats -from kallithea.lib.compat import json from kallithea.lib.markup_renderer import MarkupRenderer -from kallithea.lib.page import RepoPage -from kallithea.lib.utils2 import safe_int +from kallithea.lib.page import Page +from kallithea.lib.utils2 import safe_int, safe_str from kallithea.lib.vcs.backends.base import EmptyChangeset from kallithea.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, NodeDoesNotExistError from kallithea.lib.vcs.nodes import FileNode @@ -83,7 +84,7 @@ readme_file = f log.debug('Found README file `%s` rendering...', readme_file) - readme_data = renderer.render(readme.content, + readme_data = renderer.render(safe_str(readme.content), filename=f) break except NodeDoesNotExistError: @@ -104,8 +105,12 @@ def index(self, repo_name): p = safe_int(request.GET.get('page'), 1) size = safe_int(request.GET.get('size'), 10) - collection = c.db_repo_scm_instance - c.cs_pagination = RepoPage(collection, page=p, items_per_page=size) + try: + collection = c.db_repo_scm_instance.get_changesets(reverse=True) + except EmptyRepositoryError as e: + h.flash(e, category='warning') + collection = [] + c.cs_pagination = Page(collection, page=p, items_per_page=size) page_revisions = [x.raw_id for x in list(c.cs_pagination)] c.cs_comments = c.db_repo.get_comments(page_revisions) c.cs_statuses = c.db_repo.statuses(page_revisions) @@ -133,17 +138,13 @@ c.stats_percentage = 0 if stats and stats.languages: - c.no_data = False is c.db_repo.enable_statistics - lang_stats_d = json.loads(stats.languages) - + lang_stats_d = ext_json.loads(stats.languages) lang_stats = [(x, {"count": y, "desc": LANGUAGES_EXTENSIONS_MAP.get(x, '?')}) for x, y in lang_stats_d.items()] lang_stats.sort(key=lambda k: (-k[1]['count'], k[0])) - c.trending_languages = lang_stats[:10] else: - c.no_data = True c.trending_languages = [] c.enable_downloads = c.db_repo.enable_downloads @@ -171,7 +172,7 @@ c.no_data_msg = _('Statistics are disabled for this repository') td = date.today() + timedelta(days=1) - td_1m = td - timedelta(days=calendar.mdays[td.month]) + td_1m = td - timedelta(days=calendar.monthrange(td.year, td.month)[1]) td_1y = td - timedelta(days=365) ts_min_m = mktime(td_1m.timetuple()) @@ -185,18 +186,16 @@ .scalar() c.stats_percentage = 0 if stats and stats.languages: - c.no_data = False is c.db_repo.enable_statistics - lang_stats_d = json.loads(stats.languages) - c.commit_data = json.loads(stats.commit_activity) - c.overview_data = json.loads(stats.commit_activity_combined) + c.commit_data = ext_json.loads(stats.commit_activity) + c.overview_data = ext_json.loads(stats.commit_activity_combined) - lang_stats = ((x, {"count": y, - "desc": LANGUAGES_EXTENSIONS_MAP.get(x)}) - for x, y in lang_stats_d.items()) + lang_stats_d = ext_json.loads(stats.languages) + lang_stats = [(x, {"count": y, + "desc": LANGUAGES_EXTENSIONS_MAP.get(x, '?')}) + for x, y in lang_stats_d.items()] + lang_stats.sort(key=lambda k: (-k[1]['count'], k[0])) + c.trending_languages = lang_stats[:10] - c.trending_languages = ( - sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10] - ) last_rev = stats.stat_on_revision + 1 c.repo_last_rev = c.db_repo_scm_instance.count() \ if c.db_repo_scm_instance.revisions else 0 @@ -208,8 +207,7 @@ else: c.commit_data = {} c.overview_data = ([[ts_min_y, 0], [ts_max_y, 10]]) - c.trending_languages = {} - c.no_data = True + c.trending_languages = [] recurse_limit = 500 # don't recurse more than 500 times when parsing get_commits_stats(c.db_repo.repo_name, ts_min_y, ts_max_y, recurse_limit) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/be/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/be/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/be/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2017-08-20 10:44+0000\n" "Last-Translator: Viktar Vauchkevich \n" "Language-Team: Belarusian %s" msgstr "Паказаць адрозненні разам %s->%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "Параўнанне" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "і" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "на %s больш" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "версіі" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "Імя форка %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "Pull-запыт %s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "[выдалены] рэпазітар" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "[створаны] рэпазітар" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[створаны] рэпазітар як форк" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "[форкнуты] рэпазітар" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "[абноўлены] рэпазітар" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "[загружаны] архіў з рэпазітара" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "[выдалены] рэпазітар" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "[створаны] карыстальнік" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "[абноўлены] карыстальнік" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "[створана] група карыстальнікаў" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "[абноўлена] група карыстальнікаў" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "[каментар] да рэвізіі ў рэпазітары" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "[каментар] у pull-запыце для" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "[зачынены] pull-запыт для" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[адпраўлена] у" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "[каміт праз Kallithea] у рэпазітары" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "[занесены з аддаленага рэпазітара] у рэпазітар" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[занесены] з" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "[дададзены ў назіранні] рэпазітар" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "[выдалены з назірання] рэпазітар" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " і на %s больш" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Няма файлаў" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "новы файл" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "зменены" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "выдалены" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "пераназваны" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1272,34 +1272,36 @@ "пераназваны з файлавай сістэмы. Калі ласка, перазапусціце прыкладанне для " "сканавання рэпазітароў" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" @@ -1307,7 +1309,7 @@ msgstr[1] "%d гады" msgstr[2] "%d гадоў" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" @@ -1315,7 +1317,7 @@ msgstr[1] "%d месяцы" msgstr[2] "%d месяцаў" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" @@ -1323,7 +1325,7 @@ msgstr[1] "%d дні" msgstr[2] "%d дзён" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" @@ -1331,7 +1333,7 @@ msgstr[1] "%d гадзіны" msgstr[2] "%d гадзін" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" @@ -1339,7 +1341,7 @@ msgstr[1] "%d хвіліны" msgstr[2] "%d хвілін" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" @@ -1347,27 +1349,27 @@ msgstr[1] "%d секунды" msgstr[2] "%d секунд" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "у %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "%s назад" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "у %s і %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s і %s назад" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "цяпер" @@ -1376,137 +1378,137 @@ msgid "on line %s" msgstr "на радку %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Згадванне]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "верхні ўзровень" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "Адміністратар Kallithea" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" -msgstr "Адміністратар Kallithea" - -#: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 #, fuzzy msgid "Default user has read access to new repositories" msgstr "Несанкцыянаваны доступ да рэсурсу" -#: kallithea/model/db.py:1641 +#: kallithea/model/db.py:1638 #, fuzzy msgid "Default user has write access to new repositories" msgstr "Несанкцыянаваны доступ да рэсурсу" +#: kallithea/model/db.py:1639 +msgid "Default user has admin access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1641 +msgid "Default user has no access to new repository groups" +msgstr "" + #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" -msgstr "" +msgid "Only admins can create repository groups" +msgstr "Толькі адміністратары могуць ствараць групы репазітароў" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" -msgstr "" +msgid "Non-admins can create repository groups" +msgstr "Неадміністратары могуць ствараць групы репазітароў" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" -msgstr "Толькі адміністратары могуць ствараць групы репазітароў" +msgid "Only admins can create user groups" +msgstr "Толькі адміністратары могуць ствараць групы карыстальнікаў" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" -msgstr "Неадміністратары могуць ствараць групы репазітароў" +msgid "Non-admins can create user groups" +msgstr "Неадміністратары могуць ствараць групы карыстальнікаў" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" -msgstr "Толькі адміністратары могуць ствараць групы карыстальнікаў" +msgid "Only admins can create top level repositories" +msgstr "Толькі адміністратары могуць ствараць рэпазітары верхняга ўзроўню" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" -msgstr "Неадміністратары могуць ствараць групы карыстальнікаў" - -#: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" -msgstr "Толькі адміністратары могуць ствараць рэпазітары верхняга ўзроўню" - -#: kallithea/model/db.py:1661 msgid "Non-admins can create top level repositories" msgstr "Неадміністратары могуць ствараць рэпазітары верхняга ўзроўню" -#: kallithea/model/db.py:1663 +#: kallithea/model/db.py:1660 msgid "" "Repository creation enabled with write permission to a repository group" msgstr "" -#: kallithea/model/db.py:1664 +#: kallithea/model/db.py:1661 msgid "" "Repository creation disabled with write permission to a repository group" msgstr "" +#: kallithea/model/db.py:1663 +msgid "Only admins can fork repositories" +msgstr "Месцазнаходжанне рэпазітароў" + +#: kallithea/model/db.py:1664 +msgid "Non-admins can fork repositories" +msgstr "" + #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" -msgstr "Месцазнаходжанне рэпазітароў" +msgid "Registration disabled" +msgstr "Рэгістрацыя адключаная" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "Рэгістрацыя адключаная" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "Рэгістрацыя карыстальніка з ручной актывацыяй уліковага запісу" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "Рэгістрацыя карыстальніка з аўтаматычнай актывацыяй" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 msgid "Not reviewed" msgstr "Не прагледжана" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 msgid "Under review" msgstr "На разглядзе" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 #, fuzzy #| msgid "Approved" msgid "Not approved" msgstr "Ухвалена" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "Ухвалена" @@ -1532,7 +1534,7 @@ msgid "Name must not contain only digits" msgstr "Імя не можа ўтрымліваць толькі лічбы" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, fuzzy, python-format #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s" msgid "" @@ -1540,72 +1542,72 @@ "%(branch)s" msgstr "[пракаментавана] у запыце на занясенне змен для" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "Новы карыстальнік \"%(new_username)s\" зарэгістраваны" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "Зачынены" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" "%(user)s просіць вас разгледзець pull request %(pr_nice_id)s: %(pr_title)s" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 #, fuzzy #| msgid "Error creating pull request: %s" msgid "Cannot create empty pull request" msgstr "Памылка пры стварэнні pull-запыту: %s" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 #, fuzzy #| msgid "Confirm to delete this pull request" msgid "You are not authorized to create the pull request" msgstr "Пацвердзіце выдаленне гэтага pull-request'а" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 #, fuzzy #| msgid "Missing changesets since the previous pull request:" msgid "Missing changesets since the previous iteration:" msgstr "Адсутныя рэвізіі адносна папярэдняга pull-запыту:" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, fuzzy, python-format #| msgid "New changesets on %s %s since the previous pull request:" msgid "New changesets on %s %s since the previous iteration:" msgstr "Новыя рэвізіі на %s %s адносна папярэдняга pull-запыту:" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, fuzzy, python-format msgid "" "This iteration is based on another %s revision and there is no simple " @@ -1613,49 +1615,49 @@ msgstr "" "Гэты pull-запыт заснаваны на іншай рэвізіі %s, просты diff немагчымы." -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, fuzzy, python-format #| msgid "No changes found on %s %s since previous version." msgid "No changes found on %s %s since previous iteration." msgstr "Няма змен на %s %s адносна папярэдняй версіі." -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "апошняя версія" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Changeset %s not found" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Набор змен %s не знойдзены" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "Рэгістрацыя новага карыстальніка" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" "Вы не можаце выдаліць карыстальніка, паколькі гэта крытычна для працы " "ўсёй праграмы" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " @@ -1665,7 +1667,7 @@ "таму не можа быць выдалены. Змяніце ўладальніка ці выдаліце гэтыя " "рэпазітары: %s" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " @@ -1675,7 +1677,7 @@ "і таму не можа быць выдалены. Змяніце ўладальніка ці выдаліце гэтая " "групы: %s" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " @@ -1685,15 +1687,15 @@ "карыстальнікаў і таму не можа быць выдалены. Змяніце ўладальніка ці " "выдаліце гэтыя групы: %s" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "Спасылка скіду пароля" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "Паведамленне пра скіданне пароля" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2403,7 +2405,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3490,7 +3492,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "Захаваць налады" @@ -3738,13 +3740,13 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repository Size" msgid "Repository page size" msgstr "Памер рэпазітара" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 #, fuzzy msgid "" "Number of items displayed in the repository pages before pagination is " @@ -3753,43 +3755,43 @@ "Колькасць элементаў, што паказваюцца на галоўнай старонцы панэлі " "кіравання перад паказам нумарацыі старонак." -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "Абразкі" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "Паказваць абразкі публічных рэпазітароў" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "Паказваць абразкі прыватных рэпазітароў" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "Паказваць абразкі публічных рэпазітароў." -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "Метатэгаванне" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4431,23 +4433,23 @@ msgid "Merge" msgstr "звесці" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "Перанесена з:" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "Заменена:" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "Замяняе:" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4457,7 +4459,7 @@ msgstr[1] "%s файлы зменена" msgstr[2] "%s файлаў зменена" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4467,8 +4469,8 @@ msgstr[1] "%s файлы зменена: %s даданні, %s выдаленні" msgstr[2] "%s файлаў зменена: %s даданняў, %s выдаленняў" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5477,45 +5479,45 @@ msgid "Stats gathered: " msgstr "Атрыманая статыстыка: " -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "файлы" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "Паказаць яшчэ" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "commit'ы" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "файлы дададзены" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "файлы зменены" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "файлы выдалены" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "файлы выдалены" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "commit" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "файл выдалены" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "файл зменены" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "файл выдалены" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/bg/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/bg/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/bg/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.4.99\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -18,14 +18,14 @@ "Generated-By: Babel 2.6.0\n" #: kallithea/controllers/changelog.py:67 -#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602 +#: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:602 msgid "There are no changesets yet" msgstr "" #: kallithea/controllers/admin/permissions.py:64 #: kallithea/controllers/admin/permissions.py:68 #: kallithea/controllers/admin/permissions.py:72 -#: kallithea/controllers/changelog.py:137 +#: kallithea/controllers/changelog.py:136 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7 @@ -34,36 +34,36 @@ msgid "None" msgstr "" -#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189 +#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:189 msgid "(closed)" msgstr "" -#: kallithea/controllers/changeset.py:81 +#: kallithea/controllers/changeset.py:82 msgid "Show whitespace" msgstr "" -#: kallithea/controllers/changeset.py:88 -#: kallithea/controllers/changeset.py:95 +#: kallithea/controllers/changeset.py:89 +#: kallithea/controllers/changeset.py:96 #: kallithea/templates/files/diff_2way.html:55 msgid "Ignore whitespace" msgstr "" -#: kallithea/controllers/changeset.py:161 +#: kallithea/controllers/changeset.py:162 #, python-format msgid "Increase diff context to %(num)s lines" msgstr "" -#: kallithea/controllers/changeset.py:201 +#: kallithea/controllers/changeset.py:202 msgid "No permission to change status" msgstr "" -#: kallithea/controllers/changeset.py:212 +#: kallithea/controllers/changeset.py:213 #, python-format msgid "Successfully deleted pull request %s" msgstr "" -#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89 -#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700 +#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89 +#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697 msgid "Such revision does not exist for this repository" msgstr "" @@ -76,61 +76,61 @@ msgid "Cannot compare repositories of different types" msgstr "" -#: kallithea/controllers/compare.py:246 +#: kallithea/controllers/compare.py:247 msgid "Cannot show empty diff" msgstr "" -#: kallithea/controllers/compare.py:248 +#: kallithea/controllers/compare.py:249 msgid "No ancestor found for merge diff" msgstr "" -#: kallithea/controllers/compare.py:252 +#: kallithea/controllers/compare.py:253 msgid "Multiple merge ancestors found for merge compare" msgstr "" -#: kallithea/controllers/compare.py:268 +#: kallithea/controllers/compare.py:269 msgid "Cannot compare repositories without using common ancestor" msgstr "" +#: kallithea/controllers/error.py:70 +msgid "No response" +msgstr "" + #: kallithea/controllers/error.py:71 -msgid "No response" -msgstr "" - -#: kallithea/controllers/error.py:72 msgid "Unknown error" msgstr "" -#: kallithea/controllers/error.py:85 +#: kallithea/controllers/error.py:84 msgid "" "The request could not be understood by the server due to malformed syntax." msgstr "" -#: kallithea/controllers/error.py:88 +#: kallithea/controllers/error.py:87 msgid "Unauthorized access to resource" msgstr "" -#: kallithea/controllers/error.py:90 +#: kallithea/controllers/error.py:89 msgid "You don't have permission to view this page" msgstr "" -#: kallithea/controllers/error.py:92 +#: kallithea/controllers/error.py:91 msgid "The resource could not be found" msgstr "" -#: kallithea/controllers/error.py:94 +#: kallithea/controllers/error.py:93 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "" -#: kallithea/controllers/feed.py:63 +#: kallithea/controllers/feed.py:59 #, python-format msgid "%s committed on %s" msgstr "" -#: kallithea/controllers/feed.py:88 -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/controllers/feed.py:84 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/compare/compare_diff.html:95 #: kallithea/templates/pullrequests/pullrequest_show.html:309 @@ -138,12 +138,12 @@ msgid "Changeset was too big and was cut off..." msgstr "" -#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140 +#: kallithea/controllers/feed.py:107 #, python-format msgid "%s %s feed" msgstr "" -#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142 +#: kallithea/controllers/feed.py:109 #, python-format msgid "Changes on %s repository" msgstr "" @@ -161,90 +161,90 @@ msgid "%s at %s" msgstr "" -#: kallithea/controllers/files.py:296 +#: kallithea/controllers/files.py:295 msgid "You can only delete files with revision being a valid branch" msgstr "" -#: kallithea/controllers/files.py:307 +#: kallithea/controllers/files.py:306 #, python-format msgid "Deleted file %s via Kallithea" msgstr "" -#: kallithea/controllers/files.py:331 +#: kallithea/controllers/files.py:330 #, python-format msgid "Successfully deleted file %s" msgstr "" -#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394 -#: kallithea/controllers/files.py:469 +#: kallithea/controllers/files.py:334 kallithea/controllers/files.py:392 +#: kallithea/controllers/files.py:467 msgid "Error occurred during commit" msgstr "" -#: kallithea/controllers/files.py:350 +#: kallithea/controllers/files.py:349 msgid "You can only edit files with revision being a valid branch" msgstr "" -#: kallithea/controllers/files.py:364 +#: kallithea/controllers/files.py:363 #, python-format msgid "Edited file %s via Kallithea" msgstr "" -#: kallithea/controllers/files.py:380 +#: kallithea/controllers/files.py:378 msgid "No changes" msgstr "" -#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458 +#: kallithea/controllers/files.py:388 kallithea/controllers/files.py:456 #, python-format msgid "Successfully committed to %s" msgstr "" -#: kallithea/controllers/files.py:409 +#: kallithea/controllers/files.py:407 msgid "Added file via Kallithea" msgstr "" -#: kallithea/controllers/files.py:430 +#: kallithea/controllers/files.py:428 msgid "No content" msgstr "" -#: kallithea/controllers/files.py:434 +#: kallithea/controllers/files.py:432 msgid "No filename" msgstr "" -#: kallithea/controllers/files.py:461 +#: kallithea/controllers/files.py:459 msgid "Location must be relative path and must not contain .. in path" msgstr "" -#: kallithea/controllers/files.py:493 +#: kallithea/controllers/files.py:491 msgid "Downloads disabled" msgstr "" +#: kallithea/controllers/files.py:502 +#, python-format +msgid "Unknown revision %s" +msgstr "" + #: kallithea/controllers/files.py:504 -#, python-format -msgid "Unknown revision %s" +msgid "Empty repository" msgstr "" #: kallithea/controllers/files.py:506 -msgid "Empty repository" -msgstr "" - -#: kallithea/controllers/files.py:508 msgid "Unknown archive type" msgstr "" -#: kallithea/controllers/files.py:729 +#: kallithea/controllers/files.py:726 #: kallithea/templates/changeset/changeset_range.html:9 #: kallithea/templates/email_templates/pull_request.html:64 #: kallithea/templates/pullrequests/pullrequest.html:84 msgid "Changesets" msgstr "" -#: kallithea/controllers/files.py:730 -#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676 +#: kallithea/controllers/files.py:727 +#: kallithea/controllers/pullrequests.py:174 kallithea/model/scm.py:663 msgid "Branches" msgstr "" -#: kallithea/controllers/files.py:731 -#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687 +#: kallithea/controllers/files.py:728 +#: kallithea/controllers/pullrequests.py:175 kallithea/model/scm.py:674 msgid "Tags" msgstr "" @@ -253,11 +253,11 @@ msgid "An error occurred during repository forking %s" msgstr "" -#: kallithea/controllers/home.py:79 +#: kallithea/controllers/home.py:77 msgid "Groups" msgstr "" -#: kallithea/controllers/home.py:89 +#: kallithea/controllers/home.py:87 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90 #: kallithea/templates/admin/repos/repo_add.html:12 #: kallithea/templates/admin/repos/repo_add.html:16 @@ -269,194 +269,194 @@ msgid "Repositories" msgstr "" -#: kallithea/controllers/home.py:122 +#: kallithea/controllers/home.py:119 #: 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:128 +#: kallithea/controllers/home.py:125 msgid "Closed Branches" msgstr "" -#: kallithea/controllers/home.py:134 +#: kallithea/controllers/home.py:131 msgid "Tag" msgstr "" -#: kallithea/controllers/home.py:140 +#: kallithea/controllers/home.py:137 msgid "Bookmark" msgstr "" -#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154 +#: kallithea/controllers/journal.py:146 kallithea/controllers/journal.py:157 #: kallithea/templates/journal/public_journal.html:4 #: kallithea/templates/journal/public_journal.html:18 msgid "Public Journal" msgstr "" -#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158 +#: kallithea/controllers/journal.py:150 kallithea/controllers/journal.py:161 #: kallithea/templates/base/base.html:290 #: kallithea/templates/journal/journal.html:5 #: kallithea/templates/journal/journal.html:13 msgid "Journal" msgstr "" -#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185 +#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184 msgid "Bad captcha" msgstr "" -#: kallithea/controllers/login.py:146 +#: kallithea/controllers/login.py:145 #, python-format msgid "You have successfully registered with %s" msgstr "" -#: kallithea/controllers/login.py:190 +#: kallithea/controllers/login.py:189 msgid "A password reset confirmation code has been sent" msgstr "" -#: kallithea/controllers/login.py:239 +#: kallithea/controllers/login.py:236 msgid "Invalid password reset token" msgstr "" #: kallithea/controllers/admin/my_account.py:157 -#: kallithea/controllers/login.py:244 +#: kallithea/controllers/login.py:241 msgid "Successfully updated password" msgstr "" -#: kallithea/controllers/pullrequests.py:68 +#: kallithea/controllers/pullrequests.py:67 #, python-format msgid "Invalid reviewer \"%s\" specified" msgstr "" -#: kallithea/controllers/pullrequests.py:131 +#: kallithea/controllers/pullrequests.py:123 #, python-format msgid "%s (closed)" msgstr "" -#: kallithea/controllers/pullrequests.py:158 +#: kallithea/controllers/pullrequests.py:150 #: kallithea/templates/changeset/changeset.html:12 msgid "Changeset" msgstr "" -#: kallithea/controllers/pullrequests.py:179 +#: kallithea/controllers/pullrequests.py:171 msgid "Special" msgstr "" -#: kallithea/controllers/pullrequests.py:180 +#: kallithea/controllers/pullrequests.py:172 msgid "Peer branches" msgstr "" -#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682 +#: kallithea/controllers/pullrequests.py:173 kallithea/model/scm.py:669 msgid "Bookmarks" msgstr "" -#: kallithea/controllers/pullrequests.py:318 +#: kallithea/controllers/pullrequests.py:315 #, python-format msgid "Error creating pull request: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:345 -#: kallithea/controllers/pullrequests.py:368 +#: kallithea/controllers/pullrequests.py:342 +#: kallithea/controllers/pullrequests.py:365 msgid "Error occurred while creating pull request" msgstr "" -#: kallithea/controllers/pullrequests.py:350 +#: kallithea/controllers/pullrequests.py:347 msgid "Successfully opened new pull request" msgstr "" -#: kallithea/controllers/pullrequests.py:373 +#: kallithea/controllers/pullrequests.py:370 msgid "New pull request iteration created" msgstr "" -#: kallithea/controllers/pullrequests.py:401 +#: kallithea/controllers/pullrequests.py:398 #, python-format msgid "Meanwhile, the following reviewers have been added: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:405 +#: kallithea/controllers/pullrequests.py:402 #, python-format msgid "Meanwhile, the following reviewers have been removed: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:421 -#: kallithea/model/pull_request.py:232 +#: kallithea/controllers/pullrequests.py:418 +#: kallithea/model/pull_request.py:230 msgid "No description" msgstr "" -#: kallithea/controllers/pullrequests.py:430 +#: kallithea/controllers/pullrequests.py:427 msgid "Pull request updated" msgstr "" -#: kallithea/controllers/pullrequests.py:443 +#: kallithea/controllers/pullrequests.py:440 msgid "Successfully deleted pull request" msgstr "" -#: kallithea/controllers/pullrequests.py:479 +#: kallithea/controllers/pullrequests.py:476 #, python-format msgid "Revision %s not found in %s" msgstr "" -#: kallithea/controllers/pullrequests.py:506 +#: kallithea/controllers/pullrequests.py:504 #, python-format msgid "Error: changesets not found when displaying pull request from %s." msgstr "" +#: kallithea/controllers/pullrequests.py:518 +#, python-format +msgid "This pull request has already been merged to %s." +msgstr "" + #: kallithea/controllers/pullrequests.py:520 -#, python-format -msgid "This pull request has already been merged to %s." -msgstr "" - -#: kallithea/controllers/pullrequests.py:522 msgid "This pull request has been closed and can not be updated." msgstr "" -#: kallithea/controllers/pullrequests.py:546 +#: kallithea/controllers/pullrequests.py:539 #, python-format msgid "The following additional changes are available on %s:" msgstr "" -#: kallithea/controllers/pullrequests.py:548 -#: kallithea/controllers/pullrequests.py:552 +#: kallithea/controllers/pullrequests.py:541 +#: kallithea/controllers/pullrequests.py:545 msgid "No additional changesets found for iterating on this pull request." msgstr "" +#: kallithea/controllers/pullrequests.py:553 +#, python-format +msgid "Note: Branch %s has another head: %s." +msgstr "" + #: kallithea/controllers/pullrequests.py:560 -#, python-format -msgid "Note: Branch %s has another head: %s." -msgstr "" - -#: kallithea/controllers/pullrequests.py:567 msgid "Git pull requests don't support iterating yet." msgstr "" -#: kallithea/controllers/pullrequests.py:569 +#: kallithea/controllers/pullrequests.py:562 #, python-format msgid "" "Error: some changesets not found when displaying pull request from %s." msgstr "" -#: kallithea/controllers/pullrequests.py:593 +#: kallithea/controllers/pullrequests.py:586 msgid "The diff can't be shown - the PR revisions could not be found." msgstr "" +#: kallithea/controllers/search.py:132 +msgid "Invalid search query. Try quoting it." +msgstr "" + #: kallithea/controllers/search.py:136 -msgid "Invalid search query. Try quoting it." -msgstr "" - -#: kallithea/controllers/search.py:140 msgid "The server has no search index." msgstr "" -#: kallithea/controllers/search.py:143 +#: kallithea/controllers/search.py:139 msgid "An error occurred during search operation." msgstr "" -#: kallithea/controllers/summary.py:168 -#: kallithea/templates/summary/summary.html:412 +#: kallithea/controllers/summary.py:169 +#: kallithea/templates/summary/summary.html:410 msgid "No data ready yet" msgstr "" -#: kallithea/controllers/summary.py:171 +#: kallithea/controllers/summary.py:172 #: kallithea/templates/summary/summary.html:97 msgid "Statistics are disabled for this repository" msgstr "" @@ -469,80 +469,80 @@ msgid "error occurred during update of auth settings" msgstr "" -#: kallithea/controllers/admin/defaults.py:75 +#: kallithea/controllers/admin/defaults.py:74 msgid "Default settings updated successfully" msgstr "" -#: kallithea/controllers/admin/defaults.py:90 +#: kallithea/controllers/admin/defaults.py:89 msgid "Error occurred during update of defaults" msgstr "" #: kallithea/controllers/admin/gists.py:59 #: kallithea/controllers/admin/my_account.py:232 -#: kallithea/controllers/admin/users.py:248 +#: kallithea/controllers/admin/users.py:246 msgid "Forever" msgstr "" #: kallithea/controllers/admin/gists.py:60 #: kallithea/controllers/admin/my_account.py:233 -#: kallithea/controllers/admin/users.py:249 +#: kallithea/controllers/admin/users.py:247 msgid "5 minutes" msgstr "" #: kallithea/controllers/admin/gists.py:61 #: kallithea/controllers/admin/my_account.py:234 -#: kallithea/controllers/admin/users.py:250 +#: kallithea/controllers/admin/users.py:248 msgid "1 hour" msgstr "" #: kallithea/controllers/admin/gists.py:62 #: kallithea/controllers/admin/my_account.py:235 -#: kallithea/controllers/admin/users.py:251 +#: kallithea/controllers/admin/users.py:249 msgid "1 day" msgstr "" #: kallithea/controllers/admin/gists.py:63 #: kallithea/controllers/admin/my_account.py:236 -#: kallithea/controllers/admin/users.py:252 +#: kallithea/controllers/admin/users.py:250 msgid "1 month" msgstr "" #: kallithea/controllers/admin/gists.py:67 #: kallithea/controllers/admin/my_account.py:238 -#: kallithea/controllers/admin/users.py:254 +#: kallithea/controllers/admin/users.py:252 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65 #: kallithea/templates/admin/users/user_edit_api_keys.html:65 msgid "Lifetime" msgstr "" -#: kallithea/controllers/admin/gists.py:142 +#: kallithea/controllers/admin/gists.py:148 msgid "Error occurred during gist creation" msgstr "" -#: kallithea/controllers/admin/gists.py:158 +#: kallithea/controllers/admin/gists.py:164 #, python-format msgid "Deleted gist %s" msgstr "" -#: kallithea/controllers/admin/gists.py:198 +#: kallithea/controllers/admin/gists.py:207 msgid "Unmodified" msgstr "" -#: kallithea/controllers/admin/gists.py:228 +#: kallithea/controllers/admin/gists.py:237 msgid "Successfully updated gist content" msgstr "" -#: kallithea/controllers/admin/gists.py:233 +#: kallithea/controllers/admin/gists.py:242 msgid "Successfully updated gist data" msgstr "" -#: kallithea/controllers/admin/gists.py:236 +#: kallithea/controllers/admin/gists.py:245 #, python-format msgid "Error occurred during update of gist %s" msgstr "" -#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211 -#: kallithea/model/user.py:232 +#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209 +#: kallithea/model/user.py:230 msgid "You can't edit this user since it's crucial for entire application" msgstr "" @@ -551,7 +551,7 @@ msgstr "" #: kallithea/controllers/admin/my_account.py:134 -#: kallithea/controllers/admin/users.py:181 +#: kallithea/controllers/admin/users.py:179 #, python-format msgid "Error occurred during update of user %s" msgstr "" @@ -561,44 +561,44 @@ msgstr "" #: kallithea/controllers/admin/my_account.py:209 -#: kallithea/controllers/admin/users.py:367 +#: kallithea/controllers/admin/users.py:365 #, python-format msgid "Added email %s to user" msgstr "" #: kallithea/controllers/admin/my_account.py:215 -#: kallithea/controllers/admin/users.py:373 +#: kallithea/controllers/admin/users.py:371 msgid "An error occurred during email saving" msgstr "" #: kallithea/controllers/admin/my_account.py:224 -#: kallithea/controllers/admin/users.py:383 +#: kallithea/controllers/admin/users.py:381 msgid "Removed email from user" msgstr "" #: kallithea/controllers/admin/my_account.py:248 -#: kallithea/controllers/admin/users.py:271 +#: kallithea/controllers/admin/users.py:269 msgid "API key successfully created" msgstr "" #: kallithea/controllers/admin/my_account.py:257 -#: kallithea/controllers/admin/users.py:281 +#: kallithea/controllers/admin/users.py:279 msgid "API key successfully reset" msgstr "" #: kallithea/controllers/admin/my_account.py:261 -#: kallithea/controllers/admin/users.py:285 +#: kallithea/controllers/admin/users.py:283 msgid "API key successfully deleted" msgstr "" #: kallithea/controllers/admin/my_account.py:281 -#: kallithea/controllers/admin/users.py:456 +#: kallithea/controllers/admin/users.py:454 #, python-format msgid "SSH key %s successfully added" msgstr "" #: kallithea/controllers/admin/my_account.py:293 -#: kallithea/controllers/admin/users.py:470 +#: kallithea/controllers/admin/users.py:468 msgid "SSH key successfully deleted" msgstr "" @@ -674,11 +674,11 @@ msgid "Allowed with automatic account activation" msgstr "" -#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673 +#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670 msgid "Manual activation of external account" msgstr "" -#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674 +#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671 msgid "Automatic activation of external account" msgstr "" @@ -700,59 +700,59 @@ msgid "Error occurred during update of permissions" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:172 +#: kallithea/controllers/admin/repo_groups.py:167 #, python-format msgid "Error occurred during creation of repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:177 +#: kallithea/controllers/admin/repo_groups.py:174 #, python-format msgid "Created repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:224 +#: kallithea/controllers/admin/repo_groups.py:221 #, python-format msgid "Updated repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:240 +#: kallithea/controllers/admin/repo_groups.py:237 #, python-format msgid "Error occurred during update of repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:250 +#: kallithea/controllers/admin/repo_groups.py:247 #, python-format msgid "This group contains %s repositories and cannot be deleted" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:257 +#: kallithea/controllers/admin/repo_groups.py:254 #, python-format msgid "This group contains %s subgroups and cannot be deleted" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:263 +#: kallithea/controllers/admin/repo_groups.py:260 #, python-format msgid "Removed repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:268 +#: kallithea/controllers/admin/repo_groups.py:265 #, python-format msgid "Error occurred during deletion of repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:352 -#: kallithea/controllers/admin/repo_groups.py:382 -#: kallithea/controllers/admin/user_groups.py:294 +#: kallithea/controllers/admin/repo_groups.py:349 +#: kallithea/controllers/admin/repo_groups.py:379 +#: kallithea/controllers/admin/user_groups.py:292 msgid "Cannot revoke permission for yourself as admin" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:367 +#: kallithea/controllers/admin/repo_groups.py:364 msgid "Repository group permissions updated" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:399 +#: kallithea/controllers/admin/repo_groups.py:396 #: kallithea/controllers/admin/repos.py:358 -#: kallithea/controllers/admin/user_groups.py:306 +#: kallithea/controllers/admin/user_groups.py:304 msgid "An error occurred during revoking of permission" msgstr "" @@ -878,7 +878,7 @@ msgid "Updated VCS settings" msgstr "" -#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237 +#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238 msgid "" "Unable to activate hgsubversion support. The \"hgsubversion\" library is " "missing" @@ -943,96 +943,96 @@ msgid "Whoosh reindex task scheduled" msgstr "" -#: kallithea/controllers/admin/user_groups.py:138 +#: kallithea/controllers/admin/user_groups.py:136 #, python-format msgid "Created user group %s" msgstr "" -#: kallithea/controllers/admin/user_groups.py:151 +#: kallithea/controllers/admin/user_groups.py:149 #, python-format msgid "Error occurred during creation of user group %s" msgstr "" -#: kallithea/controllers/admin/user_groups.py:179 +#: kallithea/controllers/admin/user_groups.py:177 #, python-format msgid "Updated user group %s" msgstr "" -#: kallithea/controllers/admin/user_groups.py:201 +#: kallithea/controllers/admin/user_groups.py:199 #, python-format msgid "Error occurred during update of user group %s" msgstr "" -#: kallithea/controllers/admin/user_groups.py:212 +#: kallithea/controllers/admin/user_groups.py:210 msgid "Successfully deleted user group" msgstr "" -#: kallithea/controllers/admin/user_groups.py:217 +#: kallithea/controllers/admin/user_groups.py:215 msgid "An error occurred during deletion of user group" msgstr "" -#: kallithea/controllers/admin/user_groups.py:273 +#: kallithea/controllers/admin/user_groups.py:271 msgid "Target group cannot be the same" msgstr "" -#: kallithea/controllers/admin/user_groups.py:279 +#: kallithea/controllers/admin/user_groups.py:277 msgid "User group permissions updated" msgstr "" -#: kallithea/controllers/admin/user_groups.py:388 -#: kallithea/controllers/admin/users.py:338 +#: kallithea/controllers/admin/user_groups.py:386 +#: kallithea/controllers/admin/users.py:336 msgid "Updated permissions" msgstr "" -#: kallithea/controllers/admin/user_groups.py:392 -#: kallithea/controllers/admin/users.py:342 +#: kallithea/controllers/admin/user_groups.py:390 +#: kallithea/controllers/admin/users.py:340 msgid "An error occurred during permissions saving" msgstr "" -#: kallithea/controllers/admin/users.py:123 +#: kallithea/controllers/admin/users.py:121 #, python-format msgid "Created user %s" msgstr "" -#: kallithea/controllers/admin/users.py:138 +#: kallithea/controllers/admin/users.py:136 #, python-format msgid "Error occurred during creation of user %s" msgstr "" -#: kallithea/controllers/admin/users.py:162 +#: kallithea/controllers/admin/users.py:160 msgid "User updated successfully" msgstr "" -#: kallithea/controllers/admin/users.py:190 +#: kallithea/controllers/admin/users.py:188 msgid "Successfully deleted user" msgstr "" -#: kallithea/controllers/admin/users.py:195 +#: kallithea/controllers/admin/users.py:193 msgid "An error occurred during deletion of user" msgstr "" -#: kallithea/controllers/admin/users.py:203 +#: kallithea/controllers/admin/users.py:201 msgid "The default user cannot be edited" msgstr "" -#: kallithea/controllers/admin/users.py:409 +#: kallithea/controllers/admin/users.py:407 #, python-format msgid "Added IP address %s to user whitelist" msgstr "" -#: kallithea/controllers/admin/users.py:415 +#: kallithea/controllers/admin/users.py:413 msgid "An error occurred while adding IP address" msgstr "" -#: kallithea/controllers/admin/users.py:427 +#: kallithea/controllers/admin/users.py:425 msgid "Removed IP address from user whitelist" msgstr "" -#: kallithea/lib/auth.py:684 +#: kallithea/lib/auth.py:668 msgid "You need to be a registered user to perform this action" msgstr "" -#: kallithea/lib/auth.py:712 +#: kallithea/lib/auth.py:696 msgid "You need to be signed in to view this page" msgstr "" @@ -1063,170 +1063,170 @@ "Changeset was too big and was cut off, use diff menu to display this diff" msgstr "" -#: kallithea/lib/diffs.py:224 +#: kallithea/lib/diffs.py:223 msgid "No changes detected" msgstr "" -#: kallithea/lib/helpers.py:653 +#: kallithea/lib/helpers.py:646 #, python-format msgid "Deleted branch: %s" msgstr "" -#: kallithea/lib/helpers.py:655 +#: kallithea/lib/helpers.py:648 #, python-format msgid "Created tag: %s" msgstr "" -#: kallithea/lib/helpers.py:666 +#: kallithea/lib/helpers.py:659 #, python-format msgid "Changeset %s not found" msgstr "" -#: kallithea/lib/helpers.py:715 +#: kallithea/lib/helpers.py:708 #, python-format msgid "Show all combined changesets %s->%s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1234,96 +1234,98 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1332,133 +1334,133 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1484,145 +1486,145 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" -msgstr "" - -#: kallithea/model/user.py:186 +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2311,7 +2313,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3354,7 +3356,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3594,53 +3596,53 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4268,23 +4270,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4293,7 +4295,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4302,8 +4304,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5263,45 +5265,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/cs/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/cs/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/cs/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2015-11-12 08:51+0000\n" "Last-Translator: Michal Čihař \n" "Language-Team: Czech %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1243,34 +1243,36 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" @@ -1278,7 +1280,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" @@ -1286,7 +1288,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" @@ -1294,7 +1296,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" @@ -1302,7 +1304,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" @@ -1310,7 +1312,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" @@ -1318,27 +1320,27 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1347,135 +1349,135 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1666 #, fuzzy msgid "Only admins can fork repositories" msgstr "Chyba při vytváření repozitáře %s" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 #, fuzzy msgid "Non-admins can fork repositories" msgstr "Chyba při vytváření repozitáře %s" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1501,146 +1503,146 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Set changeset status" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Změny" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2332,7 +2334,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3397,7 +3399,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 #, fuzzy msgid "Save Settings" msgstr "Nastavení" @@ -3639,56 +3641,56 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repositories" msgid "Repository page size" msgstr "Repozitáře" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 #, fuzzy msgid "Meta Tagging" msgstr "Nastavení" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4320,23 +4322,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4346,7 +4348,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4356,8 +4358,8 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5344,45 +5346,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/da/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/da/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/da/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3.99\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-03-14 01:03+0000\n" "Last-Translator: Allan Nordhøy \n" "Language-Team: Danish %s" msgstr "Vis alle kombineret changesets %s->%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "Sammenlign visning" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "og" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "%s flere" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "revisioner" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "Fork-navn %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "Pull-forespørgsel %s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "[slettet] repository" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "[oprettet] repository" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[oprettet] repository som fork" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "[forked] repository" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "[opdateret] repository" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "[hentet] arkiv fra repository" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "[slettet] repository" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "[oprettet] bruger" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "[opdateret] bruger" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "[oprettet] brugergruppe" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "[opdateret] brugergruppe" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "[kommenterede] på revision i repository" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "[kommenterede] på pull-forespørgsel for" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "[lukket] pull-forespørgsel for" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[pushed] ind i" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "[committed via kallithea] ind i repository" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "[pulled fra remote] ind i repository" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[pulled] fra" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "[begyndt at følge] repository" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "[stoppet at følge] repository" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " og %s flere" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Ingen filer" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "ny fil" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "mod" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "del" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "omdøb" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1270,96 +1270,98 @@ "%s repository er ikke knyttet til db, måske var det skabt eller omdøbt " "fra filsystemet, kør applikationen igen for at scanne repositories" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "i %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "%s siden" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "i %s og %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s og %s siden" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "lige nu" @@ -1368,136 +1370,136 @@ msgid "on line %s" msgstr "på linje %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Omtale]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "top-niveau" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "Kallithea Administrator" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "Standard-bruger har ikke adgang til nye repositories" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" -msgstr "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "Standard-bruger har læse-adgang til nye repositories" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" +msgstr "Standard-bruger har skrive-adgang til nye repositories" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "Standard-bruger har ikke adgang til nye repositories" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" -msgstr "Standard-bruger har læse-adgang til nye repositories" +msgid "Default user has admin access to new repositories" +msgstr "Standard-bruger har admin-adgang til nye repositories" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" -msgstr "Standard-bruger har skrive-adgang til nye repositories" - -#: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" -msgstr "Standard-bruger har admin-adgang til nye repositories" - -#: kallithea/model/db.py:1644 msgid "Default user has no access to new repository groups" msgstr "Standard-bruger har ikke adgang til nye repository-grupper" -#: kallithea/model/db.py:1645 +#: kallithea/model/db.py:1642 msgid "Default user has read access to new repository groups" msgstr "Standard-bruger har læse-adgang til nye repository-grupper" -#: kallithea/model/db.py:1646 +#: kallithea/model/db.py:1643 msgid "Default user has write access to new repository groups" msgstr "Standard-bruger har skrive-adgang til nye repository-grupper" -#: kallithea/model/db.py:1647 +#: kallithea/model/db.py:1644 msgid "Default user has admin access to new repository groups" msgstr "Standard-bruger har admin-adgang til nye repository-grupper" -#: kallithea/model/db.py:1649 +#: kallithea/model/db.py:1646 msgid "Default user has no access to new user groups" msgstr "Standard-bruger har ikke adgang til nye brugergrupper" -#: kallithea/model/db.py:1650 +#: kallithea/model/db.py:1647 msgid "Default user has read access to new user groups" msgstr "Standard-bruger har læse-adgang til nye brugergrupper" +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" +msgstr "Standard-bruger har skrive-adgang til nye brugergrupper" + +#: kallithea/model/db.py:1649 +msgid "Default user has admin access to new user groups" +msgstr "Standard-bruger har admin-adgang til nye brugergrupper" + #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" -msgstr "Standard-bruger har skrive-adgang til nye brugergrupper" +msgid "Only admins can create repository groups" +msgstr "Kun administratorer kan oprette repository-grupper" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" -msgstr "Standard-bruger har admin-adgang til nye brugergrupper" +msgid "Non-admins can create repository groups" +msgstr "Ikke-administratorer kan oprette repository-grupper" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" -msgstr "Kun administratorer kan oprette repository-grupper" +msgid "Only admins can create user groups" +msgstr "Kun administratorer kan oprette brugergrupper" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" -msgstr "Ikke-administratorer kan oprette repository-grupper" - -#: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" -msgstr "Kun administratorer kan oprette brugergrupper" - -#: kallithea/model/db.py:1658 msgid "Non-admins can create user groups" msgstr "Ikke-administratorer kan oprette brugergrupper" -#: kallithea/model/db.py:1660 +#: kallithea/model/db.py:1657 msgid "Only admins can create top level repositories" msgstr "Kun administratorer kan oprette top-niveau repositories" -#: kallithea/model/db.py:1661 +#: kallithea/model/db.py:1658 msgid "Non-admins can create top level repositories" msgstr "Ikke-administratorer kan oprette top-niveau repositories" -#: kallithea/model/db.py:1663 +#: kallithea/model/db.py:1660 msgid "" "Repository creation enabled with write permission to a repository group" msgstr "" "Repository oprettelse aktiveret med skriveadgang til en repository-gruppe" -#: kallithea/model/db.py:1664 +#: kallithea/model/db.py:1661 msgid "" "Repository creation disabled with write permission to a repository group" msgstr "" "Repository oprettelse deaktiveret med skriveadgang til en repository-" "gruppe" -#: kallithea/model/db.py:1666 +#: kallithea/model/db.py:1663 msgid "Only admins can fork repositories" msgstr "Kun admins kan fork repositories" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 msgid "Non-admins can fork repositories" msgstr "Ikke-administratorer kan forke repositories" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "Registrering deaktiveret" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "Brugerregistrering med manuel kontoaktivering" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "Brugerregistrering med automatisk kontoaktivering" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 msgid "Not reviewed" msgstr "Ikke gennemgået" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 msgid "Under review" msgstr "Under gennemgang" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 msgid "Not approved" msgstr "Ikke godkendt" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "Godkendt" @@ -1523,7 +1525,7 @@ msgid "Name must not contain only digits" msgstr "Navn må ikke kun indeholde cifre" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " @@ -1532,12 +1534,12 @@ "[Kommentar] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" på " "%(branch)s" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "Ny bruger %(new_username)s registreret" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " @@ -1546,7 +1548,7 @@ "[Gennemgang] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" fra " "%(pr_source_branch)s af %(pr_owner_username)s" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " @@ -1555,11 +1557,11 @@ "[Kommentar] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" fra " "%(pr_source_branch)s af %(pr_owner_username)s" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "Lukning" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" @@ -1567,110 +1569,110 @@ "%(user)s vil have dig til at gennemgå pull-forespørgsel %(pr_nice_id)s: " "%(pr_title)s" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "Kan ikke oprette en tom pull-forespørgsel" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Changeset %s not found" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Changeset %s ikke fundet" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2359,7 +2361,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3402,7 +3404,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3642,53 +3644,53 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4317,23 +4319,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4342,7 +4344,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4351,8 +4353,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5316,45 +5318,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/de/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/de/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/de/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-05-29 22:52+0000\n" "Last-Translator: ssantos \n" "Language-Team: German %s" msgstr "Zeige alle Kombinierten Änderungensätze %s->%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "Vergleichsansicht" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "und" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "%s mehr" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "revisionen" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "Fork Name %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "Pull Request %s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "[gelöscht] Repository" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "[erstellt] Repository" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[erstellt] Repository als Fork" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "[forked] Repository" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "[aktualisiert] Repository" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "Archiv von Repository [heruntergeladen]" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "Repository [gelöscht]" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "Benutzer [erstellt]" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "Benutzer [akutalisiert]" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "Benutzergruppe [erstellt]" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "Benutzergruppe [aktualisiert]" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "Revision [kommentiert] in Repository" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "Pull Request [kommentiert] für" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "Pull Request [geschlossen] für" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[Pushed] in" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "[via Kallithea] in Repository [committed]" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "[Pulled von Remote] in Repository" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[Pulled] von" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "[Following gestartet] für Repository" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "[Following gestoppt] für Repository" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " und %s weitere" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Keine Dateien" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "neue Datei" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "mod" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "entf" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "umbenennen" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1303,96 +1303,98 @@ "es im Dateisystem erstellt oder umbenannt. Bitte starten sie die " "Applikation erneut um die Repositories neu zu Indizieren" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d Jahr" msgstr[1] "%d Jahre" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d Monat" msgstr[1] "%d Monate" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d Tag" msgstr[1] "%d Tage" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d Stunde" msgstr[1] "%d Stunden" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d Minute" msgstr[1] "%d Minuten" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d Sekunde" msgstr[1] "%d Sekunden" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "in %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "vor %s" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "in %s und %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s und %s her" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "jetzt gerade" @@ -1401,140 +1403,140 @@ msgid "on line %s" msgstr "in Zeile %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Mention]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "höchste Ebene" -#: kallithea/model/db.py:1637 +#: kallithea/model/db.py:1634 msgid "Kallithea Administrator" msgstr "Kallithea Administrator" -#: kallithea/model/db.py:1639 +#: kallithea/model/db.py:1636 msgid "Default user has no access to new repositories" msgstr "Der Standard-Benutzer hat keinen Zugriff auf neue Repositories" -#: kallithea/model/db.py:1640 +#: kallithea/model/db.py:1637 msgid "Default user has read access to new repositories" msgstr "Der Standard-Benutzer hat Leserechte auf neuen Repositories" -#: kallithea/model/db.py:1641 +#: kallithea/model/db.py:1638 msgid "Default user has write access to new repositories" msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Repositories" -#: kallithea/model/db.py:1642 +#: kallithea/model/db.py:1639 msgid "Default user has admin access to new repositories" msgstr "Der Standard-Benutzer hat Admin-Rechte auf neuen Repositories" -#: kallithea/model/db.py:1644 +#: kallithea/model/db.py:1641 msgid "Default user has no access to new repository groups" msgstr "" "Der Standard-Benutzer hat keinen Zugriff auf neue Repository-Gruppen" -#: kallithea/model/db.py:1645 +#: kallithea/model/db.py:1642 msgid "Default user has read access to new repository groups" msgstr "Der Standard-Benutzer hat Leserechte auf neuen Repository-Gruppen" +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" +msgstr "Der Standard-Benutzer Schreibrechte auf neuen Repository-Gruppen" + +#: kallithea/model/db.py:1644 +msgid "Default user has admin access to new repository groups" +msgstr "Der Standard-Benutzer Admin-Rechte auf neuen Repository-Gruppen" + #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" -msgstr "Der Standard-Benutzer Schreibrechte auf neuen Repository-Gruppen" +msgid "Default user has no access to new user groups" +msgstr "Der Standard-Benutzer hat keinen Zugriff auf neue Benutzer-Gruppen" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" -msgstr "Der Standard-Benutzer Admin-Rechte auf neuen Repository-Gruppen" +msgid "Default user has read access to new user groups" +msgstr "Der Standard-Benutzer hat Leserechte auf neuen Benutzer-Gruppen" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" +msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Benutzer-Gruppen" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "Der Standard-Benutzer hat keinen Zugriff auf neue Benutzer-Gruppen" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" -msgstr "Der Standard-Benutzer hat Leserechte auf neuen Benutzer-Gruppen" - -#: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" -msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Benutzer-Gruppen" - -#: kallithea/model/db.py:1652 msgid "Default user has admin access to new user groups" msgstr "Der Standard-Benutzer hat Admin-Rechte auf neuen Benutzer-Gruppen" -#: kallithea/model/db.py:1654 +#: kallithea/model/db.py:1651 msgid "Only admins can create repository groups" msgstr "Nur Admins können Repository-Gruppen erstellen" +#: kallithea/model/db.py:1652 +msgid "Non-admins can create repository groups" +msgstr "Nicht-Admins können Repository-Gruppen erstellen" + +#: kallithea/model/db.py:1654 +msgid "Only admins can create user groups" +msgstr "Nur Admins können Benutzer-Gruppen erstellen" + #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" -msgstr "Nicht-Admins können Repository-Gruppen erstellen" +msgid "Non-admins can create user groups" +msgstr "Nicht-Admins können Benutzer-Gruppen erstellen" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" -msgstr "Nur Admins können Benutzer-Gruppen erstellen" +msgid "Only admins can create top level repositories" +msgstr "Nur Admins können Repositories auf oberster Ebene erstellen" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" -msgstr "Nicht-Admins können Benutzer-Gruppen erstellen" +msgid "Non-admins can create top level repositories" +msgstr "Nicht-Admins können Repositories oberster Ebene erstellen" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" -msgstr "Nur Admins können Repositories auf oberster Ebene erstellen" - -#: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" -msgstr "Nicht-Admins können Repositories oberster Ebene erstellen" - -#: kallithea/model/db.py:1663 msgid "" "Repository creation enabled with write permission to a repository group" msgstr "" "Erstellung von Repositories mit Schreibzugriff für Repositorygruppe " "aktiviert" -#: kallithea/model/db.py:1664 +#: kallithea/model/db.py:1661 msgid "" "Repository creation disabled with write permission to a repository group" msgstr "" "Erstellung von Repositories mit Schreibzugriff für Repositorygruppe " "deaktiviert" -#: kallithea/model/db.py:1666 +#: kallithea/model/db.py:1663 msgid "Only admins can fork repositories" msgstr "Nur Admins können Repositories forken" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 msgid "Non-admins can fork repositories" msgstr "Nicht-Admins können Repositorys forken" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "Registrierung deaktiviert" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "Benutzerregistrierung mit manueller Kontoaktivierung" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "Benutzerregistrierung mit automatischer Kontoaktivierung" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 msgid "Not reviewed" msgstr "Nicht Begutachtet" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 msgid "Under review" msgstr "In Begutachtung" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 #, fuzzy #| msgid "Approved" msgid "Not approved" msgstr "Akzeptiert" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "Akzeptiert" @@ -1560,7 +1562,7 @@ msgid "Name must not contain only digits" msgstr "Name darf nicht nur Ziffern enthalten" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, fuzzy, python-format #| msgid "[Comment] %(repo_name)s changeset %(short_id)s on %(branch)s" msgid "" @@ -1570,43 +1572,43 @@ "Kommentar für %(repo_name)s Changeset %(short_id)s in %(branch)s erstellt " "von %(comment_username)s" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "Neuer Benutzer %(new_username)s registriert" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "Schließen" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, fuzzy, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" "%(user)s möchte ein Review des Pull Request #%(pr_id)s: %(pr_title)s" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 #, fuzzy #| msgid "Error creating pull request: %s" msgid "Cannot create empty pull request" msgstr "Fehler beim Erstellen des Pull-Requests: %s" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " @@ -1615,29 +1617,29 @@ "Pull-Request kann nicht erstellt werden - Criss Cross Merge erkannt, " "bitte eine spätere %s-Revision in %s zusammenführen." -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "Sie sind nicht berechtigt, den Pull-Request anzulegen." -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 #, fuzzy #| msgid "Missing changesets since the previous pull request:" msgid "Missing changesets since the previous iteration:" msgstr "Fehlende Changesets seit letztem Pull Request:" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, fuzzy, python-format #| msgid "New changesets on %s %s since the previous pull request:" msgid "New changesets on %s %s since the previous iteration:" msgstr "Neue Changesets in %s %s seit dem letzten Pull Request:" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 #, fuzzy #| msgid "Ancestor didn't change - show diff since previous version:" msgid "Ancestor didn't change - diff since previous iteration:" msgstr "Vorgänger unverändert - zeige Diff zu lezter Version:" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, fuzzy, python-format msgid "" "This iteration is based on another %s revision and there is no simple " @@ -1646,42 +1648,42 @@ "Dieser Pull Request basiert auf einer anderen %s Revision. Daher ist kein " "Simple Diff verfügbar." -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, fuzzy, python-format #| msgid "No changes found on %s %s since previous version." msgid "No changes found on %s %s since previous iteration." msgstr "Keine Änderungen seit der letzten Version gefunden in %s %s." -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "Geschlossen, nächste Iteration: %s ." -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "Letzter Tip" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Changeset not found" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Änderungssatz nicht gefunden" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "Neue Benutzerregistrierung" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 #, fuzzy msgid "" "You can't remove this user since it is crucial for the entire application" @@ -1689,7 +1691,7 @@ "Sie können diesen Benutzer nicht löschen, da er von entscheidender " "Bedeutung für die gesamte Applikation ist" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " @@ -1699,7 +1701,7 @@ "nicht entfernt werden. Entweder muss der Besitzer geändert oder das " "Repository entfernt werden: %s" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " @@ -1709,7 +1711,7 @@ "kann daher nicht entfernt werden. Entweder muss der Besitzer geändert " "oder die Repositorygruppen müssen entfernt werden: %s" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " @@ -1719,16 +1721,16 @@ "nicht entfernt werden. Entweder muss der Besitzer geändert oder die " "Benutzergruppen müssen gelöscht werden: %s" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "Link zum Zurücksetzen des Passworts" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 #, fuzzy msgid "Password reset notification" msgstr "Link zum Zurücksetzen des Passworts" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2464,7 +2466,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3595,7 +3597,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "Einstellungen speichern" @@ -3914,13 +3916,13 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repository Size" msgid "Repository page size" msgstr "Repository Größe" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." @@ -3928,11 +3930,11 @@ "Anzahl der Elemente, die auf den Repository-Seiten angezeigt werden, " "bevor der Seitenumbruch angezeigt wird." -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "Größe der Admin-Seite" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." @@ -3940,29 +3942,29 @@ "Anzahl der Elemente, die in den Gittern der Admin-Seiten angezeigt " "werden, bevor der Seitenumbruch angezeigt wird." -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "Icons" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "Öffentliches Repository-Symbol in Repositories anzeigen" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "Privates Repository-Symbol in Repositories anzeigen" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" "Zeigt öffentliche/private Symbole neben den Namen der Repositories an." -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 #, fuzzy msgid "Meta Tagging" msgstr "Einstellungen" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." @@ -3970,7 +3972,7 @@ "Analysiert Meta-Tags aus dem Beschreibungsfeld des Repositorys und " "verwandelt sie in farbige Tags." -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "Erkannte Meta-Tags stilisieren:" @@ -4610,25 +4612,25 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 #, fuzzy msgid "Replaced by:" msgstr "Erstellt von" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 #, fuzzy msgid "Preceded by:" msgstr "Erstellt von" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4637,7 +4639,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4646,8 +4648,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5655,45 +5657,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "Dateien" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "Mehr anzeigen" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "Commits" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "Dateien hinzugefügt" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "Dateien geändert" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "Dateien entfernt" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "Dateien entfernt" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "Commit" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "Datei hinzugefügt" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "Datei geändert" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "Datei entfernt" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/el/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/el/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/el/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-06-26 19:00+0000\n" "Last-Translator: THANOS SIOURDAKIS \n" "Language-Team: Greek %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1275,96 +1275,98 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1373,133 +1375,133 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1525,79 +1527,79 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 #, fuzzy #| msgid "Error creating pull request: %s" msgid "Cannot create empty pull request" msgstr "Λάθος στη δημιουργία αιτήματος έλξης - pull request: %s" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 #, fuzzy #| msgid "Missing changesets since the previous pull request:" msgid "Missing changesets since the previous iteration:" msgstr "Ελλιπή σετ αλλαγών από την προηγούμενη αίτηση έλξης:" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, fuzzy, python-format #| msgid "New changesets on %s %s since the previous pull request:" msgid "New changesets on %s %s since the previous iteration:" msgstr "Καινούρια σετ αλλαγών στα %s %s από την προηγούμενη αίτηση έλξης:" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 #, fuzzy #| msgid "Ancestor didn't change - show diff since previous version:" msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" "Το γονικό δεν άλλαξε - εμφάνισε τις διαφορές από την προηγούμενη έκδοση:" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, fuzzy, python-format #| msgid "" #| "This pull request is based on another %s revision and there is no " @@ -1609,75 +1611,75 @@ "Αυτή η αίτηση έλξης είναι βασισμένη σε μία άλλη %s αναθεώρηση και δεν " "υπάρχει ένα απλό diff." -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, fuzzy, python-format #| msgid "No changes found on %s %s since previous version." msgid "No changes found on %s %s since previous iteration." msgstr "Δεν βρέθηκαν αλλαγές στο %s %s από την προηγούμενη έκδοση." -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" -msgstr "" - -#: kallithea/model/user.py:186 +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2366,7 +2368,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3416,7 +3418,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3656,55 +3658,55 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repositories" msgid "Repository page size" msgstr "Αποθετήρια" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4333,23 +4335,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4358,7 +4360,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4367,8 +4369,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5349,45 +5351,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/es/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/es/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/es/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2018-04-18 11:43+0000\n" "Last-Translator: Jesús Sánchez \n" "Language-Team: Spanish %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1259,96 +1259,98 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1357,133 +1359,133 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1509,79 +1511,79 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 #, fuzzy #| msgid "Error creating pull request: %s" msgid "Cannot create empty pull request" msgstr "Error al crear la petición de pull: %s" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 #, fuzzy #| msgid "Missing changesets since the previous pull request:" msgid "Missing changesets since the previous iteration:" msgstr "Cambios que faltan desde la ultima petición de pull:" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, fuzzy, python-format #| msgid "New changesets on %s %s since the previous pull request:" msgid "New changesets on %s %s since the previous iteration:" msgstr "Cambios nuevos en %s %s desde la ultima petición pull:" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 #, fuzzy #| msgid "Ancestor didn't change - show diff since previous version:" msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" "El ascendente no ha cambiado - ver diferencias desde la versión anterior:" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, fuzzy, python-format msgid "" "This iteration is based on another %s revision and there is no simple " @@ -1590,75 +1592,75 @@ "La petición de pull está basada en otra %s revisión y no hay un diff " "simple." -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, fuzzy, python-format #| msgid "No changes found on %s %s since previous version." msgid "No changes found on %s %s since previous iteration." msgstr "No se encontró ningún cambio en %s %s desde la versión anterior." -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" -msgstr "" - -#: kallithea/model/user.py:186 +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2347,7 +2349,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3394,7 +3396,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3634,55 +3636,55 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repositories" msgid "Repository page size" msgstr "Repositorios" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4311,23 +4313,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4336,7 +4338,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4345,8 +4347,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5323,45 +5325,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/fr/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/fr/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/fr/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-10-13 16:52+0000\n" "Last-Translator: Nathan \n" "Language-Team: French %s" msgstr "Afficher les changements combinés %s->%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "Vue de comparaison" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "et" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "%s de plus" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "révisions" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "Nom du fork %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "Requête de pull %s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "[a supprimé] le dépôt" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "[a créé] le dépôt" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[a créé] le dépôt en tant que fork" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "[a forké] le dépôt" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "[a mis à jour] le dépôt" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "[téléchargée] archive depuis le dépôt" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "[a supprimé] le dépôt" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "[a créé] l’utilisateur" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "[a mis à jour] l’utilisateur" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "[créé] groupe d'utilisateurs" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "[mis à jour] groupe d'utilisateurs" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "[a commenté] une révision du dépôt" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "[a commenté] la requête de pull pour" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "[a fermé] la requête de pull de" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[a pushé] dans" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "[a commité via Kallithea] dans le dépôt" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "[a pullé depuis un site distant] dans le dépôt" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[a pullé] depuis" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "[suit maintenant] le dépôt" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "[ne suit plus] le dépôt" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " et %s de plus" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Aucun fichier" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "nouveau fichier" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "mod" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "suppr." -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "renommer" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1288,96 +1288,98 @@ "probablement été créé ou renommé manuellement. Veuillez relancer " "l’application pour rescanner les dépôts" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d an" msgstr[1] "%d ans" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d mois" msgstr[1] "%d mois" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d jour" msgstr[1] "%d jours" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d heure" msgstr[1] "%d heures" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minute" msgstr[1] "%d minutes" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d seconde" msgstr[1] "%d secondes" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "dans %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "Il y a %s" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "dans %s et %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "Il y a %s et %s" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "à l’instant" @@ -1386,158 +1388,158 @@ msgid "on line %s" msgstr "à la ligne %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Mention]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "niveau supérieur" -#: kallithea/model/db.py:1637 +#: kallithea/model/db.py:1634 msgid "Kallithea Administrator" msgstr "Administrateur Kallithea" +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "L'utilisateur par défaut n'a pas accès aux nouveaux dépôts" + +#: kallithea/model/db.py:1637 +msgid "Default user has read access to new repositories" +msgstr "L'utilisateur par défaut a un accès en lecture aux nouveaux dépôts" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" +msgstr "L'utilisateur par défaut a un accès en écriture aux nouveaux dépôts" + #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "L'utilisateur par défaut n'a pas accès aux nouveaux dépôts" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" -msgstr "L'utilisateur par défaut a un accès en lecture aux nouveaux dépôts" - -#: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" -msgstr "L'utilisateur par défaut a un accès en écriture aux nouveaux dépôts" - -#: kallithea/model/db.py:1642 msgid "Default user has admin access to new repositories" msgstr "" "L'utilisateur par défaut a un accès administrateur aux nouveaux dépôts" -#: kallithea/model/db.py:1644 +#: kallithea/model/db.py:1641 msgid "Default user has no access to new repository groups" msgstr "" "L'utilisateur par défaut n'a pas accès aux nouveaux groupes de dépôts" -#: kallithea/model/db.py:1645 +#: kallithea/model/db.py:1642 msgid "Default user has read access to new repository groups" msgstr "" "L'utilisateur par défaut a accès en lecture seule aux nouveaux groupes de " "dépôts" -#: kallithea/model/db.py:1646 +#: kallithea/model/db.py:1643 msgid "Default user has write access to new repository groups" msgstr "" "L'utilisateur par défaut a accès en écriture aux nouveaux groupes de " "dépôts" -#: kallithea/model/db.py:1647 +#: kallithea/model/db.py:1644 msgid "Default user has admin access to new repository groups" msgstr "" "L'utilisateur par défaut a accès administrateur aux nouveaux groupes de " "dépôts" -#: kallithea/model/db.py:1649 +#: kallithea/model/db.py:1646 msgid "Default user has no access to new user groups" msgstr "" "L'utilisateur par défaut n'a pas accès aux nouveaux groupes d'utilisateurs" -#: kallithea/model/db.py:1650 +#: kallithea/model/db.py:1647 msgid "Default user has read access to new user groups" msgstr "" "L'utilisateur par défaut a accès en lecture seule aux nouveaux groupes " "d'utilisateurs" -#: kallithea/model/db.py:1651 +#: kallithea/model/db.py:1648 msgid "Default user has write access to new user groups" msgstr "" "L'utilisateur par défaut a accès en écriture aux nouveaux groupes " "d'utilisateurs" -#: kallithea/model/db.py:1652 +#: kallithea/model/db.py:1649 msgid "Default user has admin access to new user groups" msgstr "" "L'utilisateur par défaut a un accès administrateur aux nouveaux groupes " "d'utilisateurs" -#: kallithea/model/db.py:1654 +#: kallithea/model/db.py:1651 msgid "Only admins can create repository groups" msgstr "Seul un administrateur peut créer un groupe de dépôts" -#: kallithea/model/db.py:1655 +#: kallithea/model/db.py:1652 msgid "Non-admins can create repository groups" msgstr "" "Les utilisateurs non-administrateurs peuvent créer des groupes de dépôts" -#: kallithea/model/db.py:1657 +#: kallithea/model/db.py:1654 msgid "Only admins can create user groups" msgstr "Seul un administrateur peut créer des groupes d'utilisateurs" -#: kallithea/model/db.py:1658 +#: kallithea/model/db.py:1655 msgid "Non-admins can create user groups" msgstr "" "Les utilisateurs non-administrateurs peuvent créer des groupes " "d'utilisateurs" -#: kallithea/model/db.py:1660 +#: kallithea/model/db.py:1657 msgid "Only admins can create top level repositories" msgstr "Seul un administrateur peut créer des dépôts de niveau supérieur" -#: kallithea/model/db.py:1661 +#: kallithea/model/db.py:1658 msgid "Non-admins can create top level repositories" msgstr "" "Les utilisateurs non-administrateurs peuvent créer des dépôts de niveau " "supérieur" -#: kallithea/model/db.py:1663 +#: kallithea/model/db.py:1660 msgid "" "Repository creation enabled with write permission to a repository group" msgstr "" "Création de dépôts activée avec l'accès en écriture vers un groupe de " "dépôts" -#: kallithea/model/db.py:1664 +#: kallithea/model/db.py:1661 msgid "" "Repository creation disabled with write permission to a repository group" msgstr "" "Création de dépôts désactivée avec l'accès en écriture vers un groupe de " "dépôts" -#: kallithea/model/db.py:1666 +#: kallithea/model/db.py:1663 msgid "Only admins can fork repositories" msgstr "Seul un administrateur peut faire un fork de dépôt" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 msgid "Non-admins can fork repositories" msgstr "Les utilisateurs non-administrateurs peuvent faire un fork de dépôt" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "Enregistrement désactivé" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "Enregistrement des utilisateurs avec activation de compte manuelle" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" "Enregistrement des utilisateurs avec activation de compte automatique" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 msgid "Not reviewed" msgstr "Pas encore relue" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 msgid "Under review" msgstr "En cours de relecture" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 msgid "Not approved" msgstr "Non approuvée" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "Approuvée" @@ -1563,7 +1565,7 @@ msgid "Name must not contain only digits" msgstr "Le nom ne doit pas contenir seulement des chiffres" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " @@ -1572,12 +1574,12 @@ "[Commentaire] Changeset %(short_id)s « %(message_short)s » de " "%(repo_name)s dans %(branch)s" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "Nouvel utilisateur %(new_username)s enregistré" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " @@ -1586,7 +1588,7 @@ "[Revue] %(repo_name)s PR %(pr_nice_id)s « %(pr_title_short)s » depuis " "%(pr_source_branch)s par %(pr_owner_username)s" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " @@ -1595,11 +1597,11 @@ "[Commentaire] %(repo_name)s PR %(pr_nice_id)s « %(pr_title_short)s » " "depuis %(pr_source_branch)s par %(pr_owner_username)s" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "Fermeture" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" @@ -1607,11 +1609,11 @@ "%(user)s veut que vous regardiez la demande de pull %(pr_nice_id)s : " "%(pr_title)s" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "Impossible de créer une requête de pull vide" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " @@ -1620,24 +1622,24 @@ "Impossible de créer la requête de pull : fusion croisée détectée, merci " "de fusionner une révision plus vieille de %s vers %s" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "Vous n'êtes pas autorisé à créer cette requête de pull" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "Changeset manquant depuis la précédente itération :" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "Nouveau changeset sur %s %s depuis la précédente itération :" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "L'ancêtre n'a pas changé - diff depuis l'itération précédente :" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " @@ -1646,48 +1648,48 @@ "Cette itération est basée sur une autre révision %s et il n'y a pas de " "diff simple." -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "Aucun changement constaté sur %s %s depuis l'itération précédente." -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "Fermé, itération suivante : %s." -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "Dernier sommet" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Changeset %s not found" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Ensemble de changements %s non trouvé" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "Nouveau enregistrement d'utilisateur" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" "Vous ne pouvez pas supprimer cet utilisateur ; il est nécessaire pour le " "bon fonctionnement de l’application" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " @@ -1696,7 +1698,7 @@ "L’utilisateur \"%s\" possède %s dépôts et ne peut être supprimé. Changez " "les propriétaires ou supprimez ces dépôts : %s" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " @@ -1705,7 +1707,7 @@ "L’utilisateur \"%s\" possède %s groupes de dépôt et ne peut être " "supprimé. Changez les propriétaires ou supprimez ces dépôts : %s" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " @@ -1715,15 +1717,15 @@ "être supprimé. Changez les propriétaires de ces groupes d'utilisateurs ou " "supprimez-les : %s" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "Lien de remise à zéro du mot de passe" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "Notification de réinitialisation du mot de passe" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2447,7 +2449,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3579,7 +3581,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "Enregistrer les options" @@ -3892,11 +3894,11 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "Taille de la page du dépôt" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." @@ -3904,11 +3906,11 @@ "Nombre d'éléments affichés dans les pages des dépôts avant d'afficher la " "pagination." -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "Taille de la page d'admin" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." @@ -3916,27 +3918,27 @@ "Nombre d'éléments affichés dans les grilles des pages admin avant " "d'afficher la pagination." -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "Icônes" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "Afficher l’icône de dépôt public sur les dépôts" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "Afficher l’icône de dépôt privé sur les dépôts" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "Afficher l’icône « public/privé » à côté du nom des dépôts." -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "Meta-tagging" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." @@ -3944,7 +3946,7 @@ "Analyser les méta-tags dans le champ de description du dépôt et les " "transformer en tags colorés." -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "Styliser les méta-tags reconnus :" @@ -4581,23 +4583,23 @@ msgid "Merge" msgstr "Fusion" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "Grafté depuis :" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "Transplanté depuis :" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "Remplacé par :" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "Précédé par :" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4606,7 +4608,7 @@ msgstr[0] "%s fichier changé" msgstr[1] "%s fichiers changés" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4615,8 +4617,8 @@ msgstr[0] "%s fichier changé avec %s insertions et %s suppressions" msgstr[1] "%s fichiers changés avec %s insertions et %s suppressions" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5605,45 +5607,45 @@ msgid "Stats gathered: " msgstr "Statistiques obtenues : " -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "Fichiers" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "Afficher plus" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "commits" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "fichiers ajoutés" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "fichiers modifiés" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "fichiers supprimés" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "fichiers supprimés" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "commit" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "fichier ajouté" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "fichié modifié" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "fichier supprimé" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/how_to --- a/kallithea/i18n/how_to Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/how_to Thu Feb 06 01:19:23 2020 +0100 @@ -55,9 +55,9 @@ First update the translation strings:: - python2 setup.py extract_messages + python3 setup.py extract_messages -Then regenerate the translation files. This could either be done with `python2 +Then regenerate the translation files. This could either be done with `python3 setup.py update_catalog` or with `msgmerge` from the `gettext` package. As Weblate is also touching these translation files, it is preferred to use the same tools (`msgmerge`) and settings as Weblate to minimize the diff:: @@ -73,11 +73,11 @@ In the prepared development environment, run the following to ensure all translation strings are extracted and up-to-date:: - python2 setup.py extract_messages + python3 setup.py extract_messages Create new language by executing following command:: - python2 setup.py init_catalog -l + python3 setup.py init_catalog -l This creates a new translation under directory `kallithea/i18n/` based on the translation template file, `kallithea/i18n/kallithea.pot`. @@ -90,7 +90,7 @@ Finally, compile the translations:: - python2 setup.py compile_catalog -l + python3 setup.py compile_catalog -l Manually updating translations @@ -98,11 +98,11 @@ Extract the latest versions of strings for translation by running:: - python2 setup.py extract_messages + python3 setup.py extract_messages Update the PO file by doing:: - python2 setup.py update_catalog -l + python3 setup.py update_catalog -l Edit the newly updated translation file. Repeat all steps after the `init_catalog` step from the 'new translation' instructions above. diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/hu/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/hu/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/hu/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2015-04-11 00:59+0200\n" "Last-Translator: Balázs Úr \n" "Language-Team: Hungarian %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1235,96 +1235,98 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1333,133 +1335,133 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1485,145 +1487,145 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" -msgstr "" - -#: kallithea/model/user.py:186 +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2312,7 +2314,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3363,7 +3365,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3603,53 +3605,53 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4278,23 +4280,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4303,7 +4305,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4312,8 +4314,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5285,45 +5287,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/ja/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/ja/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/ja/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-08-27 07:23+0000\n" "Last-Translator: leela <53352@protonmail.com>\n" "Language-Team: Japanese %s" msgstr "%s から %s までのすべてのチェンジセットを表示" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "比較ビュー" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "と" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "%s 以上" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "リビジョン" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "フォーク名 %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "プルリクエスト #%s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "リポジトリを[削除]" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "リポジトリを[作成]" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "フォークしてリポジトリを[作成]" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "リポジトリを[フォーク]" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "リポジトリを[更新]" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "リポジトリからアーカイブを[ダウンロード]" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "リポジトリを[削除]" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "ユーザーを[作成]" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "ユーザーを[更新]" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "ユーザーグループを[作成]" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "ユーザーグループを[更新]" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "リポジトリのリビジョンに[コメント]" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "プルリクエストに[コメント]" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "プルリクエストを[クローズ]" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[プッシュ]" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "リポジトリに[Kallithea経由でコミット]" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "リポジトリに[リモートからプル]" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[プル]" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "リポジトリの[フォローを開始]" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "リポジトリの[フォローを停止]" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " と %s 以上" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "ファイルはありません" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "新しいファイル" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "変更" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "削除" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "リネーム" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1274,90 +1274,92 @@ "られたか名前が変更されたためです。リポジトリをもう一度チェックするためにア" "プリケーションを再起動してください" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d 年" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d ヶ月" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d 日" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d 時間" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d 分" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d 秒" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "%s 以内" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "%s 前" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "%s と %s の間" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s と %s 前" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "たったいま" @@ -1366,140 +1368,140 @@ msgid "on line %s" msgstr "%s 行目" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Mention]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "top level" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "Kallithea 管理者" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "デフォルトユーザーは新しいリポジトリにアクセスできません" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" -msgstr "Kallithea 管理者" - -#: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "デフォルトユーザーは新しいリポジトリにアクセスできません" - -#: kallithea/model/db.py:1640 msgid "Default user has read access to new repositories" msgstr "" "デフォルトユーザーは新しいリポジトリに読み取りアクセスする権限があります" -#: kallithea/model/db.py:1641 +#: kallithea/model/db.py:1638 msgid "Default user has write access to new repositories" msgstr "" "デフォルトユーザーは新しいリポジトリに書き込みアクセスする権限があります" +#: kallithea/model/db.py:1639 +msgid "Default user has admin access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1641 +msgid "Default user has no access to new repository groups" +msgstr "" + #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" -msgstr "" +msgid "Only admins can create repository groups" +msgstr "管理者のみがリポジトリのグループを作成できます" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" -msgstr "" +msgid "Non-admins can create repository groups" +msgstr "非管理者がリポジトリのグループを作成できます" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" -msgstr "管理者のみがリポジトリのグループを作成できます" +msgid "Only admins can create user groups" +msgstr "管理者だけがユーザー グループを作成することができます" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" -msgstr "非管理者がリポジトリのグループを作成できます" +msgid "Non-admins can create user groups" +msgstr "非管理者ユーザーがグループを作成することができます" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" -msgstr "管理者だけがユーザー グループを作成することができます" +msgid "Only admins can create top level repositories" +msgstr "管理者だけがトップレベルにリポジトリを作成することができます" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" -msgstr "非管理者ユーザーがグループを作成することができます" +msgid "Non-admins can create top level repositories" +msgstr "非管理者がトップレベルにリポジトリを作成することができます" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" -msgstr "管理者だけがトップレベルにリポジトリを作成することができます" - -#: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" -msgstr "非管理者がトップレベルにリポジトリを作成することができます" - -#: kallithea/model/db.py:1663 msgid "" "Repository creation enabled with write permission to a repository group" msgstr "" "リポジトリグループの書き込みパーミッションを使ったリポジトリ作成が有効です" -#: kallithea/model/db.py:1664 +#: kallithea/model/db.py:1661 msgid "" "Repository creation disabled with write permission to a repository group" msgstr "" "リポジトリグループの書き込みパーミッションを使ったリポジトリ作成は無効です" -#: kallithea/model/db.py:1666 +#: kallithea/model/db.py:1663 msgid "Only admins can fork repositories" msgstr "管理者のみがリポジトリをフォークすることができます" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 #, fuzzy msgid "Non-admins can fork repositories" msgstr "非管理者がリポジトリをフォークすることができます" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "新規登録を無効にする" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "ユーザーの新規登録時に手動でアカウントをアクティベートする" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "ユーザーの新規登録時に自動でアカウントをアクティベートする" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 msgid "Not reviewed" msgstr "未レビュー" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 msgid "Under review" msgstr "レビュー中" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 #, fuzzy #| msgid "Approved" msgid "Not approved" msgstr "承認" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "承認" @@ -1525,7 +1527,7 @@ msgid "Name must not contain only digits" msgstr "数字だけの名前は使えません" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, fuzzy, python-format #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s" msgid "" @@ -1533,30 +1535,30 @@ "%(branch)s" msgstr "プルリクエストに[コメント]" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "新しいユーザー %(new_username)s が登録されました" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "クローズ" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" @@ -1564,80 +1566,80 @@ "%(user)s がプリリクエスト #%(pr_nice_id)s: %(pr_title)s のレビューを求めて" "います" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 #, fuzzy #| msgid "Error creating pull request: %s" msgid "Cannot create empty pull request" msgstr "プルリクエスト作成中にエラーが発生しました: %s" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 #, fuzzy #| msgid "Confirm to delete this pull request" msgid "You are not authorized to create the pull request" msgstr "このプルリクエストを削除してもよろしいですか?" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "最新のtip" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Changeset not found" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "リビジョンが見つかりません" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "新規ユーザー登録" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 #, fuzzy msgid "" "You can't remove this user since it is crucial for the entire application" @@ -1645,7 +1647,7 @@ "このユーザーを削除できません。このユーザーはアプリケーションにとって必要不" "可欠です。" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " @@ -1654,7 +1656,7 @@ "ユーザー \"%s\" はまだ %s 個のリポジトリの所有者のため削除することはできま" "せん。リポジトリの所有者を変更するか削除してください: %s" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " @@ -1663,7 +1665,7 @@ "ユーザー \"%s\" はまだ %s 個のリポジトリグループの所有者のため削除すること" "はできません。リポジトリグループの所有者を変更するか削除してください: %s" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " @@ -1672,15 +1674,15 @@ "ユーザー \"%s\" はまだ %s 個のユーザーグループの所有者のため削除することは" "できません。ユーザーグループの所有者を変更するか削除してください。 %s" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "パスワードリセットのリンク" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "パスワードの再設定通知" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2392,7 +2394,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3502,7 +3504,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "設定を保存" @@ -3799,13 +3801,13 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repository Size" msgid "Repository page size" msgstr "リポジトリサイズ" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 #, fuzzy #| msgid "" #| "Number of items displayed in the admin pages grids before pagination " @@ -3815,45 +3817,45 @@ "shown." msgstr "管理ページで、ページ分割しないでグリッドに表示する項目の数" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 #, fuzzy #| msgid "Admin pages items" msgid "Admin page size" msgstr "管理ページの項目" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "管理ページで、ページ分割しないでグリッドに表示する項目の数" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "アイコン" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "公開リポジトリのアイコンを表示する" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "非公開リポジトリのアイコンを表示する" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "リポジトリ名の隣に公開/非公開アイコンを表示します。" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "メタタグ" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "リポジトリの説明のメタタグを解析して色つきのタグに変換します。" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "次のメタタグを変換する:" @@ -4496,26 +4498,26 @@ msgid "Merge" msgstr "マージ" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 #, fuzzy msgid "Grafted from:" msgstr "作成日" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 #, fuzzy msgid "Replaced by:" msgstr "作成日" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 #, fuzzy msgid "Preceded by:" msgstr "作成日" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4523,7 +4525,7 @@ msgid_plural "%s files changed" msgstr[0] "%s ファイルに影響" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4531,8 +4533,8 @@ msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "%s ファイルに影響。 %s 個の追加と %s 個の削除" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5547,45 +5549,45 @@ msgid "Stats gathered: " msgstr "収集した統計情報: " -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "ファイル" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "もっと表示" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "コミット" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "追加されたファイル" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "変更されたファイル" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "削除されたファイル" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "削除されたファイル" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "コミット" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "追加されたファイル" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "変更されたファイル" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "削除されたファイル" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/kallithea.pot --- a/kallithea/i18n/kallithea.pot Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/kallithea.pot Thu Feb 06 01:19:23 2020 +0100 @@ -1,14 +1,14 @@ # Translations template for Kallithea. -# Copyright (C) 2019 Various authors, licensing as GPLv3 +# Copyright (C) 2020 Various authors, licensing as GPLv3 # This file is distributed under the same license as the Kallithea project. -# FIRST AUTHOR , 2019. +# FIRST AUTHOR , 2020. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Kallithea 0.4.99\n" +"Project-Id-Version: Kallithea 0.5.99\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,14 +18,14 @@ "Generated-By: Babel 2.7.0\n" #: kallithea/controllers/changelog.py:67 -#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602 +#: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:602 msgid "There are no changesets yet" msgstr "" #: kallithea/controllers/admin/permissions.py:64 #: kallithea/controllers/admin/permissions.py:68 #: kallithea/controllers/admin/permissions.py:72 -#: kallithea/controllers/changelog.py:137 +#: kallithea/controllers/changelog.py:136 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7 @@ -34,35 +34,35 @@ msgid "None" msgstr "" -#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189 +#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:189 msgid "(closed)" msgstr "" -#: kallithea/controllers/changeset.py:81 +#: kallithea/controllers/changeset.py:82 msgid "Show whitespace" msgstr "" -#: kallithea/controllers/changeset.py:88 kallithea/controllers/changeset.py:95 +#: kallithea/controllers/changeset.py:89 kallithea/controllers/changeset.py:96 #: kallithea/templates/files/diff_2way.html:55 msgid "Ignore whitespace" msgstr "" -#: kallithea/controllers/changeset.py:161 +#: kallithea/controllers/changeset.py:162 #, python-format msgid "Increase diff context to %(num)s lines" msgstr "" -#: kallithea/controllers/changeset.py:201 +#: kallithea/controllers/changeset.py:202 msgid "No permission to change status" msgstr "" -#: kallithea/controllers/changeset.py:212 +#: kallithea/controllers/changeset.py:213 #, python-format msgid "Successfully deleted pull request %s" msgstr "" -#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89 -#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700 +#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89 +#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697 msgid "Such revision does not exist for this repository" msgstr "" @@ -75,60 +75,60 @@ msgid "Cannot compare repositories of different types" msgstr "" -#: kallithea/controllers/compare.py:246 +#: kallithea/controllers/compare.py:247 msgid "Cannot show empty diff" msgstr "" -#: kallithea/controllers/compare.py:248 +#: kallithea/controllers/compare.py:249 msgid "No ancestor found for merge diff" msgstr "" -#: kallithea/controllers/compare.py:252 +#: kallithea/controllers/compare.py:253 msgid "Multiple merge ancestors found for merge compare" msgstr "" -#: kallithea/controllers/compare.py:268 +#: kallithea/controllers/compare.py:269 msgid "Cannot compare repositories without using common ancestor" msgstr "" +#: kallithea/controllers/error.py:70 +msgid "No response" +msgstr "" + #: kallithea/controllers/error.py:71 -msgid "No response" -msgstr "" - -#: kallithea/controllers/error.py:72 msgid "Unknown error" msgstr "" -#: kallithea/controllers/error.py:85 +#: kallithea/controllers/error.py:84 msgid "The request could not be understood by the server due to malformed syntax." msgstr "" -#: kallithea/controllers/error.py:88 +#: kallithea/controllers/error.py:87 msgid "Unauthorized access to resource" msgstr "" -#: kallithea/controllers/error.py:90 +#: kallithea/controllers/error.py:89 msgid "You don't have permission to view this page" msgstr "" -#: kallithea/controllers/error.py:92 +#: kallithea/controllers/error.py:91 msgid "The resource could not be found" msgstr "" -#: kallithea/controllers/error.py:94 +#: kallithea/controllers/error.py:93 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "" -#: kallithea/controllers/feed.py:63 +#: kallithea/controllers/feed.py:59 #, python-format msgid "%s committed on %s" msgstr "" -#: kallithea/controllers/feed.py:88 -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/controllers/feed.py:84 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/compare/compare_diff.html:95 #: kallithea/templates/pullrequests/pullrequest_show.html:309 @@ -136,12 +136,12 @@ msgid "Changeset was too big and was cut off..." msgstr "" -#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140 +#: kallithea/controllers/feed.py:107 #, python-format msgid "%s %s feed" msgstr "" -#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142 +#: kallithea/controllers/feed.py:109 #, python-format msgid "Changes on %s repository" msgstr "" @@ -159,90 +159,90 @@ msgid "%s at %s" msgstr "" -#: kallithea/controllers/files.py:296 +#: kallithea/controllers/files.py:295 msgid "You can only delete files with revision being a valid branch" msgstr "" -#: kallithea/controllers/files.py:307 +#: kallithea/controllers/files.py:306 #, python-format msgid "Deleted file %s via Kallithea" msgstr "" -#: kallithea/controllers/files.py:331 +#: kallithea/controllers/files.py:330 #, python-format msgid "Successfully deleted file %s" msgstr "" -#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394 -#: kallithea/controllers/files.py:469 +#: kallithea/controllers/files.py:334 kallithea/controllers/files.py:392 +#: kallithea/controllers/files.py:467 msgid "Error occurred during commit" msgstr "" -#: kallithea/controllers/files.py:350 +#: kallithea/controllers/files.py:349 msgid "You can only edit files with revision being a valid branch" msgstr "" -#: kallithea/controllers/files.py:364 +#: kallithea/controllers/files.py:363 #, python-format msgid "Edited file %s via Kallithea" msgstr "" -#: kallithea/controllers/files.py:380 +#: kallithea/controllers/files.py:378 msgid "No changes" msgstr "" -#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458 +#: kallithea/controllers/files.py:388 kallithea/controllers/files.py:456 #, python-format msgid "Successfully committed to %s" msgstr "" -#: kallithea/controllers/files.py:409 +#: kallithea/controllers/files.py:407 msgid "Added file via Kallithea" msgstr "" -#: kallithea/controllers/files.py:430 +#: kallithea/controllers/files.py:428 msgid "No content" msgstr "" -#: kallithea/controllers/files.py:434 +#: kallithea/controllers/files.py:432 msgid "No filename" msgstr "" -#: kallithea/controllers/files.py:461 +#: kallithea/controllers/files.py:459 msgid "Location must be relative path and must not contain .. in path" msgstr "" -#: kallithea/controllers/files.py:493 +#: kallithea/controllers/files.py:491 msgid "Downloads disabled" msgstr "" +#: kallithea/controllers/files.py:502 +#, python-format +msgid "Unknown revision %s" +msgstr "" + #: kallithea/controllers/files.py:504 -#, python-format -msgid "Unknown revision %s" +msgid "Empty repository" msgstr "" #: kallithea/controllers/files.py:506 -msgid "Empty repository" -msgstr "" - -#: kallithea/controllers/files.py:508 msgid "Unknown archive type" msgstr "" -#: kallithea/controllers/files.py:729 +#: kallithea/controllers/files.py:726 #: kallithea/templates/changeset/changeset_range.html:9 #: kallithea/templates/email_templates/pull_request.html:64 #: kallithea/templates/pullrequests/pullrequest.html:84 msgid "Changesets" msgstr "" -#: kallithea/controllers/files.py:730 kallithea/controllers/pullrequests.py:182 -#: kallithea/model/scm.py:676 +#: kallithea/controllers/files.py:727 kallithea/controllers/pullrequests.py:174 +#: kallithea/model/scm.py:663 msgid "Branches" msgstr "" -#: kallithea/controllers/files.py:731 kallithea/controllers/pullrequests.py:183 -#: kallithea/model/scm.py:687 +#: kallithea/controllers/files.py:728 kallithea/controllers/pullrequests.py:175 +#: kallithea/model/scm.py:674 msgid "Tags" msgstr "" @@ -251,11 +251,11 @@ msgid "An error occurred during repository forking %s" msgstr "" -#: kallithea/controllers/home.py:79 +#: kallithea/controllers/home.py:77 msgid "Groups" msgstr "" -#: kallithea/controllers/home.py:89 +#: kallithea/controllers/home.py:87 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90 #: kallithea/templates/admin/repos/repo_add.html:12 #: kallithea/templates/admin/repos/repo_add.html:16 @@ -266,193 +266,193 @@ msgid "Repositories" msgstr "" -#: kallithea/controllers/home.py:122 +#: kallithea/controllers/home.py:119 #: 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:128 +#: kallithea/controllers/home.py:125 msgid "Closed Branches" msgstr "" -#: kallithea/controllers/home.py:134 +#: kallithea/controllers/home.py:131 msgid "Tag" msgstr "" -#: kallithea/controllers/home.py:140 +#: kallithea/controllers/home.py:137 msgid "Bookmark" msgstr "" -#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154 +#: kallithea/controllers/journal.py:146 kallithea/controllers/journal.py:157 #: kallithea/templates/journal/public_journal.html:4 #: kallithea/templates/journal/public_journal.html:18 msgid "Public Journal" msgstr "" -#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158 +#: kallithea/controllers/journal.py:150 kallithea/controllers/journal.py:161 #: kallithea/templates/base/base.html:290 #: kallithea/templates/journal/journal.html:5 #: kallithea/templates/journal/journal.html:13 msgid "Journal" msgstr "" -#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185 +#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184 msgid "Bad captcha" msgstr "" -#: kallithea/controllers/login.py:146 +#: kallithea/controllers/login.py:145 #, python-format msgid "You have successfully registered with %s" msgstr "" -#: kallithea/controllers/login.py:190 +#: kallithea/controllers/login.py:189 msgid "A password reset confirmation code has been sent" msgstr "" -#: kallithea/controllers/login.py:239 +#: kallithea/controllers/login.py:236 msgid "Invalid password reset token" msgstr "" #: kallithea/controllers/admin/my_account.py:157 -#: kallithea/controllers/login.py:244 +#: kallithea/controllers/login.py:241 msgid "Successfully updated password" msgstr "" -#: kallithea/controllers/pullrequests.py:68 +#: kallithea/controllers/pullrequests.py:67 #, python-format msgid "Invalid reviewer \"%s\" specified" msgstr "" -#: kallithea/controllers/pullrequests.py:131 +#: kallithea/controllers/pullrequests.py:123 #, python-format msgid "%s (closed)" msgstr "" -#: kallithea/controllers/pullrequests.py:158 +#: kallithea/controllers/pullrequests.py:150 #: kallithea/templates/changeset/changeset.html:12 msgid "Changeset" msgstr "" -#: kallithea/controllers/pullrequests.py:179 +#: kallithea/controllers/pullrequests.py:171 msgid "Special" msgstr "" -#: kallithea/controllers/pullrequests.py:180 +#: kallithea/controllers/pullrequests.py:172 msgid "Peer branches" msgstr "" -#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682 +#: kallithea/controllers/pullrequests.py:173 kallithea/model/scm.py:669 msgid "Bookmarks" msgstr "" -#: kallithea/controllers/pullrequests.py:318 +#: kallithea/controllers/pullrequests.py:315 #, python-format msgid "Error creating pull request: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:345 -#: kallithea/controllers/pullrequests.py:368 +#: kallithea/controllers/pullrequests.py:342 +#: kallithea/controllers/pullrequests.py:365 msgid "Error occurred while creating pull request" msgstr "" -#: kallithea/controllers/pullrequests.py:350 +#: kallithea/controllers/pullrequests.py:347 msgid "Successfully opened new pull request" msgstr "" -#: kallithea/controllers/pullrequests.py:373 +#: kallithea/controllers/pullrequests.py:370 msgid "New pull request iteration created" msgstr "" -#: kallithea/controllers/pullrequests.py:401 +#: kallithea/controllers/pullrequests.py:398 #, python-format msgid "Meanwhile, the following reviewers have been added: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:405 +#: kallithea/controllers/pullrequests.py:402 #, python-format msgid "Meanwhile, the following reviewers have been removed: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:421 -#: kallithea/model/pull_request.py:232 +#: kallithea/controllers/pullrequests.py:418 +#: kallithea/model/pull_request.py:230 msgid "No description" msgstr "" -#: kallithea/controllers/pullrequests.py:430 +#: kallithea/controllers/pullrequests.py:427 msgid "Pull request updated" msgstr "" -#: kallithea/controllers/pullrequests.py:443 +#: kallithea/controllers/pullrequests.py:440 msgid "Successfully deleted pull request" msgstr "" -#: kallithea/controllers/pullrequests.py:479 +#: kallithea/controllers/pullrequests.py:476 #, python-format msgid "Revision %s not found in %s" msgstr "" -#: kallithea/controllers/pullrequests.py:506 +#: kallithea/controllers/pullrequests.py:504 #, python-format msgid "Error: changesets not found when displaying pull request from %s." msgstr "" +#: kallithea/controllers/pullrequests.py:518 +#, python-format +msgid "This pull request has already been merged to %s." +msgstr "" + #: kallithea/controllers/pullrequests.py:520 -#, python-format -msgid "This pull request has already been merged to %s." -msgstr "" - -#: kallithea/controllers/pullrequests.py:522 msgid "This pull request has been closed and can not be updated." msgstr "" -#: kallithea/controllers/pullrequests.py:546 +#: kallithea/controllers/pullrequests.py:539 #, python-format msgid "The following additional changes are available on %s:" msgstr "" -#: kallithea/controllers/pullrequests.py:548 -#: kallithea/controllers/pullrequests.py:552 +#: kallithea/controllers/pullrequests.py:541 +#: kallithea/controllers/pullrequests.py:545 msgid "No additional changesets found for iterating on this pull request." msgstr "" +#: kallithea/controllers/pullrequests.py:553 +#, python-format +msgid "Note: Branch %s has another head: %s." +msgstr "" + #: kallithea/controllers/pullrequests.py:560 -#, python-format -msgid "Note: Branch %s has another head: %s." -msgstr "" - -#: kallithea/controllers/pullrequests.py:567 msgid "Git pull requests don't support iterating yet." msgstr "" -#: kallithea/controllers/pullrequests.py:569 +#: kallithea/controllers/pullrequests.py:562 #, python-format msgid "Error: some changesets not found when displaying pull request from %s." msgstr "" -#: kallithea/controllers/pullrequests.py:593 +#: kallithea/controllers/pullrequests.py:586 msgid "The diff can't be shown - the PR revisions could not be found." msgstr "" +#: kallithea/controllers/search.py:132 +msgid "Invalid search query. Try quoting it." +msgstr "" + #: kallithea/controllers/search.py:136 -msgid "Invalid search query. Try quoting it." -msgstr "" - -#: kallithea/controllers/search.py:140 msgid "The server has no search index." msgstr "" -#: kallithea/controllers/search.py:143 +#: kallithea/controllers/search.py:139 msgid "An error occurred during search operation." msgstr "" -#: kallithea/controllers/summary.py:168 -#: kallithea/templates/summary/summary.html:412 +#: kallithea/controllers/summary.py:169 +#: kallithea/templates/summary/summary.html:410 msgid "No data ready yet" msgstr "" -#: kallithea/controllers/summary.py:171 +#: kallithea/controllers/summary.py:172 #: kallithea/templates/summary/summary.html:97 msgid "Statistics are disabled for this repository" msgstr "" @@ -465,80 +465,80 @@ msgid "error occurred during update of auth settings" msgstr "" -#: kallithea/controllers/admin/defaults.py:75 +#: kallithea/controllers/admin/defaults.py:74 msgid "Default settings updated successfully" msgstr "" -#: kallithea/controllers/admin/defaults.py:90 +#: kallithea/controllers/admin/defaults.py:89 msgid "Error occurred during update of defaults" msgstr "" #: kallithea/controllers/admin/gists.py:59 #: kallithea/controllers/admin/my_account.py:232 -#: kallithea/controllers/admin/users.py:248 +#: kallithea/controllers/admin/users.py:246 msgid "Forever" msgstr "" #: kallithea/controllers/admin/gists.py:60 #: kallithea/controllers/admin/my_account.py:233 -#: kallithea/controllers/admin/users.py:249 +#: kallithea/controllers/admin/users.py:247 msgid "5 minutes" msgstr "" #: kallithea/controllers/admin/gists.py:61 #: kallithea/controllers/admin/my_account.py:234 -#: kallithea/controllers/admin/users.py:250 +#: kallithea/controllers/admin/users.py:248 msgid "1 hour" msgstr "" #: kallithea/controllers/admin/gists.py:62 #: kallithea/controllers/admin/my_account.py:235 -#: kallithea/controllers/admin/users.py:251 +#: kallithea/controllers/admin/users.py:249 msgid "1 day" msgstr "" #: kallithea/controllers/admin/gists.py:63 #: kallithea/controllers/admin/my_account.py:236 -#: kallithea/controllers/admin/users.py:252 +#: kallithea/controllers/admin/users.py:250 msgid "1 month" msgstr "" #: kallithea/controllers/admin/gists.py:67 #: kallithea/controllers/admin/my_account.py:238 -#: kallithea/controllers/admin/users.py:254 +#: kallithea/controllers/admin/users.py:252 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65 #: kallithea/templates/admin/users/user_edit_api_keys.html:65 msgid "Lifetime" msgstr "" -#: kallithea/controllers/admin/gists.py:142 +#: kallithea/controllers/admin/gists.py:148 msgid "Error occurred during gist creation" msgstr "" -#: kallithea/controllers/admin/gists.py:158 +#: kallithea/controllers/admin/gists.py:164 #, python-format msgid "Deleted gist %s" msgstr "" -#: kallithea/controllers/admin/gists.py:198 +#: kallithea/controllers/admin/gists.py:207 msgid "Unmodified" msgstr "" -#: kallithea/controllers/admin/gists.py:228 +#: kallithea/controllers/admin/gists.py:237 msgid "Successfully updated gist content" msgstr "" -#: kallithea/controllers/admin/gists.py:233 +#: kallithea/controllers/admin/gists.py:242 msgid "Successfully updated gist data" msgstr "" -#: kallithea/controllers/admin/gists.py:236 +#: kallithea/controllers/admin/gists.py:245 #, python-format msgid "Error occurred during update of gist %s" msgstr "" -#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211 -#: kallithea/model/user.py:232 +#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209 +#: kallithea/model/user.py:230 msgid "You can't edit this user since it's crucial for entire application" msgstr "" @@ -547,7 +547,7 @@ msgstr "" #: kallithea/controllers/admin/my_account.py:134 -#: kallithea/controllers/admin/users.py:181 +#: kallithea/controllers/admin/users.py:179 #, python-format msgid "Error occurred during update of user %s" msgstr "" @@ -557,44 +557,44 @@ msgstr "" #: kallithea/controllers/admin/my_account.py:209 -#: kallithea/controllers/admin/users.py:367 +#: kallithea/controllers/admin/users.py:365 #, python-format msgid "Added email %s to user" msgstr "" #: kallithea/controllers/admin/my_account.py:215 -#: kallithea/controllers/admin/users.py:373 +#: kallithea/controllers/admin/users.py:371 msgid "An error occurred during email saving" msgstr "" #: kallithea/controllers/admin/my_account.py:224 -#: kallithea/controllers/admin/users.py:383 +#: kallithea/controllers/admin/users.py:381 msgid "Removed email from user" msgstr "" #: kallithea/controllers/admin/my_account.py:248 -#: kallithea/controllers/admin/users.py:271 +#: kallithea/controllers/admin/users.py:269 msgid "API key successfully created" msgstr "" #: kallithea/controllers/admin/my_account.py:257 -#: kallithea/controllers/admin/users.py:281 +#: kallithea/controllers/admin/users.py:279 msgid "API key successfully reset" msgstr "" #: kallithea/controllers/admin/my_account.py:261 -#: kallithea/controllers/admin/users.py:285 +#: kallithea/controllers/admin/users.py:283 msgid "API key successfully deleted" msgstr "" #: kallithea/controllers/admin/my_account.py:281 -#: kallithea/controllers/admin/users.py:456 +#: kallithea/controllers/admin/users.py:454 #, python-format msgid "SSH key %s successfully added" msgstr "" #: kallithea/controllers/admin/my_account.py:293 -#: kallithea/controllers/admin/users.py:470 +#: kallithea/controllers/admin/users.py:468 msgid "SSH key successfully deleted" msgstr "" @@ -670,11 +670,11 @@ msgid "Allowed with automatic account activation" msgstr "" -#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673 +#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670 msgid "Manual activation of external account" msgstr "" -#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674 +#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671 msgid "Automatic activation of external account" msgstr "" @@ -696,59 +696,59 @@ msgid "Error occurred during update of permissions" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:172 +#: kallithea/controllers/admin/repo_groups.py:167 #, python-format msgid "Error occurred during creation of repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:177 +#: kallithea/controllers/admin/repo_groups.py:174 #, python-format msgid "Created repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:224 +#: kallithea/controllers/admin/repo_groups.py:221 #, python-format msgid "Updated repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:240 +#: kallithea/controllers/admin/repo_groups.py:237 #, python-format msgid "Error occurred during update of repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:250 +#: kallithea/controllers/admin/repo_groups.py:247 #, python-format msgid "This group contains %s repositories and cannot be deleted" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:257 +#: kallithea/controllers/admin/repo_groups.py:254 #, python-format msgid "This group contains %s subgroups and cannot be deleted" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:263 +#: kallithea/controllers/admin/repo_groups.py:260 #, python-format msgid "Removed repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:268 +#: kallithea/controllers/admin/repo_groups.py:265 #, python-format msgid "Error occurred during deletion of repository group %s" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:352 -#: kallithea/controllers/admin/repo_groups.py:382 -#: kallithea/controllers/admin/user_groups.py:294 +#: kallithea/controllers/admin/repo_groups.py:349 +#: kallithea/controllers/admin/repo_groups.py:379 +#: kallithea/controllers/admin/user_groups.py:292 msgid "Cannot revoke permission for yourself as admin" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:367 +#: kallithea/controllers/admin/repo_groups.py:364 msgid "Repository group permissions updated" msgstr "" -#: kallithea/controllers/admin/repo_groups.py:399 +#: kallithea/controllers/admin/repo_groups.py:396 #: kallithea/controllers/admin/repos.py:358 -#: kallithea/controllers/admin/user_groups.py:306 +#: kallithea/controllers/admin/user_groups.py:304 msgid "An error occurred during revoking of permission" msgstr "" @@ -874,7 +874,7 @@ msgid "Updated VCS settings" msgstr "" -#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237 +#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238 msgid "" "Unable to activate hgsubversion support. The \"hgsubversion\" library is " "missing" @@ -939,96 +939,96 @@ msgid "Whoosh reindex task scheduled" msgstr "" -#: kallithea/controllers/admin/user_groups.py:138 +#: kallithea/controllers/admin/user_groups.py:136 #, python-format msgid "Created user group %s" msgstr "" -#: kallithea/controllers/admin/user_groups.py:151 +#: kallithea/controllers/admin/user_groups.py:149 #, python-format msgid "Error occurred during creation of user group %s" msgstr "" -#: kallithea/controllers/admin/user_groups.py:179 +#: kallithea/controllers/admin/user_groups.py:177 #, python-format msgid "Updated user group %s" msgstr "" -#: kallithea/controllers/admin/user_groups.py:201 +#: kallithea/controllers/admin/user_groups.py:199 #, python-format msgid "Error occurred during update of user group %s" msgstr "" -#: kallithea/controllers/admin/user_groups.py:212 +#: kallithea/controllers/admin/user_groups.py:210 msgid "Successfully deleted user group" msgstr "" -#: kallithea/controllers/admin/user_groups.py:217 +#: kallithea/controllers/admin/user_groups.py:215 msgid "An error occurred during deletion of user group" msgstr "" -#: kallithea/controllers/admin/user_groups.py:273 +#: kallithea/controllers/admin/user_groups.py:271 msgid "Target group cannot be the same" msgstr "" -#: kallithea/controllers/admin/user_groups.py:279 +#: kallithea/controllers/admin/user_groups.py:277 msgid "User group permissions updated" msgstr "" -#: kallithea/controllers/admin/user_groups.py:388 -#: kallithea/controllers/admin/users.py:338 +#: kallithea/controllers/admin/user_groups.py:386 +#: kallithea/controllers/admin/users.py:336 msgid "Updated permissions" msgstr "" -#: kallithea/controllers/admin/user_groups.py:392 -#: kallithea/controllers/admin/users.py:342 +#: kallithea/controllers/admin/user_groups.py:390 +#: kallithea/controllers/admin/users.py:340 msgid "An error occurred during permissions saving" msgstr "" -#: kallithea/controllers/admin/users.py:123 +#: kallithea/controllers/admin/users.py:121 #, python-format msgid "Created user %s" msgstr "" -#: kallithea/controllers/admin/users.py:138 +#: kallithea/controllers/admin/users.py:136 #, python-format msgid "Error occurred during creation of user %s" msgstr "" -#: kallithea/controllers/admin/users.py:162 +#: kallithea/controllers/admin/users.py:160 msgid "User updated successfully" msgstr "" -#: kallithea/controllers/admin/users.py:190 +#: kallithea/controllers/admin/users.py:188 msgid "Successfully deleted user" msgstr "" -#: kallithea/controllers/admin/users.py:195 +#: kallithea/controllers/admin/users.py:193 msgid "An error occurred during deletion of user" msgstr "" -#: kallithea/controllers/admin/users.py:203 +#: kallithea/controllers/admin/users.py:201 msgid "The default user cannot be edited" msgstr "" -#: kallithea/controllers/admin/users.py:409 +#: kallithea/controllers/admin/users.py:407 #, python-format msgid "Added IP address %s to user whitelist" msgstr "" -#: kallithea/controllers/admin/users.py:415 +#: kallithea/controllers/admin/users.py:413 msgid "An error occurred while adding IP address" msgstr "" -#: kallithea/controllers/admin/users.py:427 +#: kallithea/controllers/admin/users.py:425 msgid "Removed IP address from user whitelist" msgstr "" -#: kallithea/lib/auth.py:684 +#: kallithea/lib/auth.py:668 msgid "You need to be a registered user to perform this action" msgstr "" -#: kallithea/lib/auth.py:712 +#: kallithea/lib/auth.py:696 msgid "You need to be signed in to view this page" msgstr "" @@ -1057,169 +1057,169 @@ msgid "Changeset was too big and was cut off, use diff menu to display this diff" msgstr "" -#: kallithea/lib/diffs.py:224 +#: kallithea/lib/diffs.py:223 msgid "No changes detected" msgstr "" -#: kallithea/lib/helpers.py:653 +#: kallithea/lib/helpers.py:646 #, python-format msgid "Deleted branch: %s" msgstr "" -#: kallithea/lib/helpers.py:655 +#: kallithea/lib/helpers.py:648 #, python-format msgid "Created tag: %s" msgstr "" -#: kallithea/lib/helpers.py:666 +#: kallithea/lib/helpers.py:659 #, python-format msgid "Changeset %s not found" msgstr "" -#: kallithea/lib/helpers.py:715 +#: kallithea/lib/helpers.py:708 #, python-format msgid "Show all combined changesets %s->%s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 kallithea/templates/changelog/changelog.html:43 +#: kallithea/lib/helpers.py:735 kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1227,96 +1227,98 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1325,131 +1327,131 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1475,143 +1477,143 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" -msgstr "" - -#: kallithea/model/user.py:186 +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch" " owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2299,7 +2301,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3337,7 +3339,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3576,53 +3578,53 @@ "'ssh://{system_user}@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4246,23 +4248,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4271,7 +4273,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4280,8 +4282,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5241,45 +5243,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/lb/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/lb/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/lb/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -1,17 +1,5417 @@ # Copyright (C) 2020 Various authors, licensing as GPLv3 # This file is distributed under the same license as the Kallithea project. - msgid "" msgstr "" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "Language: lb\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +#: kallithea/controllers/changelog.py:67 +#: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:602 msgid "There are no changesets yet" msgstr "Et sinn nach keng Ännerungen do" +#: kallithea/controllers/admin/permissions.py:64 +#: kallithea/controllers/admin/permissions.py:68 +#: kallithea/controllers/admin/permissions.py:72 +#: kallithea/controllers/changelog.py:136 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:7 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7 +#: kallithea/templates/base/perms_summary.html:14 +msgid "None" +msgstr "" + +#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:189 msgid "(closed)" msgstr "(Zou)" + +#: kallithea/controllers/changeset.py:82 +msgid "Show whitespace" +msgstr "" + +#: kallithea/controllers/changeset.py:89 +#: kallithea/controllers/changeset.py:96 +#: kallithea/templates/files/diff_2way.html:55 +msgid "Ignore whitespace" +msgstr "" + +#: kallithea/controllers/changeset.py:162 +#, python-format +msgid "Increase diff context to %(num)s lines" +msgstr "" + +#: kallithea/controllers/changeset.py:202 +msgid "No permission to change status" +msgstr "" + +#: kallithea/controllers/changeset.py:213 +#, python-format +msgid "Successfully deleted pull request %s" +msgstr "" + +#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89 +#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697 +msgid "Such revision does not exist for this repository" +msgstr "" + +#: kallithea/controllers/compare.py:68 +#, python-format +msgid "Could not find other repository %s" +msgstr "" + +#: kallithea/controllers/compare.py:74 +msgid "Cannot compare repositories of different types" +msgstr "" + +#: kallithea/controllers/compare.py:247 +msgid "Cannot show empty diff" +msgstr "" + +#: kallithea/controllers/compare.py:249 +msgid "No ancestor found for merge diff" +msgstr "" + +#: kallithea/controllers/compare.py:253 +msgid "Multiple merge ancestors found for merge compare" +msgstr "" + +#: kallithea/controllers/compare.py:269 +msgid "Cannot compare repositories without using common ancestor" +msgstr "" + +#: kallithea/controllers/error.py:70 +msgid "No response" +msgstr "" + +#: kallithea/controllers/error.py:71 +msgid "Unknown error" +msgstr "" + +#: kallithea/controllers/error.py:84 +msgid "" +"The request could not be understood by the server due to malformed syntax." +msgstr "" + +#: kallithea/controllers/error.py:87 +msgid "Unauthorized access to resource" +msgstr "" + +#: kallithea/controllers/error.py:89 +msgid "You don't have permission to view this page" +msgstr "" + +#: kallithea/controllers/error.py:91 +msgid "The resource could not be found" +msgstr "" + +#: kallithea/controllers/error.py:93 +msgid "" +"The server encountered an unexpected condition which prevented it from " +"fulfilling the request." +msgstr "" + +#: kallithea/controllers/feed.py:59 +#, python-format +msgid "%s committed on %s" +msgstr "" + +#: kallithea/controllers/feed.py:84 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 +#: kallithea/templates/compare/compare_diff.html:81 +#: kallithea/templates/compare/compare_diff.html:95 +#: kallithea/templates/pullrequests/pullrequest_show.html:309 +#: kallithea/templates/pullrequests/pullrequest_show.html:333 +msgid "Changeset was too big and was cut off..." +msgstr "" + +#: kallithea/controllers/feed.py:107 +#, python-format +msgid "%s %s feed" +msgstr "" + +#: kallithea/controllers/feed.py:109 +#, python-format +msgid "Changes on %s repository" +msgstr "" + +#: kallithea/controllers/files.py:85 +msgid "Click here to add new file" +msgstr "" + +#: kallithea/controllers/files.py:86 +#, fuzzy +#| msgid "There are no changesets yet" +msgid "There are no files yet." +msgstr "Et sinn nach keng Ännerungen do" + +#: kallithea/controllers/files.py:186 +#, python-format +msgid "%s at %s" +msgstr "" + +#: kallithea/controllers/files.py:295 +msgid "You can only delete files with revision being a valid branch" +msgstr "" + +#: kallithea/controllers/files.py:306 +#, python-format +msgid "Deleted file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:330 +#, python-format +msgid "Successfully deleted file %s" +msgstr "" + +#: kallithea/controllers/files.py:334 kallithea/controllers/files.py:392 +#: kallithea/controllers/files.py:467 +msgid "Error occurred during commit" +msgstr "" + +#: kallithea/controllers/files.py:349 +msgid "You can only edit files with revision being a valid branch" +msgstr "" + +#: kallithea/controllers/files.py:363 +#, python-format +msgid "Edited file %s via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:378 +msgid "No changes" +msgstr "" + +#: kallithea/controllers/files.py:388 kallithea/controllers/files.py:456 +#, python-format +msgid "Successfully committed to %s" +msgstr "" + +#: kallithea/controllers/files.py:407 +msgid "Added file via Kallithea" +msgstr "" + +#: kallithea/controllers/files.py:428 +msgid "No content" +msgstr "" + +#: kallithea/controllers/files.py:432 +msgid "No filename" +msgstr "" + +#: kallithea/controllers/files.py:459 +msgid "Location must be relative path and must not contain .. in path" +msgstr "" + +#: kallithea/controllers/files.py:491 +msgid "Downloads disabled" +msgstr "" + +#: kallithea/controllers/files.py:502 +#, python-format +msgid "Unknown revision %s" +msgstr "" + +#: kallithea/controllers/files.py:504 +msgid "Empty repository" +msgstr "" + +#: kallithea/controllers/files.py:506 +msgid "Unknown archive type" +msgstr "" + +#: kallithea/controllers/files.py:726 +#: kallithea/templates/changeset/changeset_range.html:9 +#: kallithea/templates/email_templates/pull_request.html:64 +#: kallithea/templates/pullrequests/pullrequest.html:84 +msgid "Changesets" +msgstr "" + +#: kallithea/controllers/files.py:727 +#: kallithea/controllers/pullrequests.py:174 kallithea/model/scm.py:663 +msgid "Branches" +msgstr "" + +#: kallithea/controllers/files.py:728 +#: kallithea/controllers/pullrequests.py:175 kallithea/model/scm.py:674 +msgid "Tags" +msgstr "" + +#: kallithea/controllers/forks.py:174 +#, python-format +msgid "An error occurred during repository forking %s" +msgstr "" + +#: kallithea/controllers/home.py:77 +msgid "Groups" +msgstr "" + +#: kallithea/controllers/home.py:87 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90 +#: 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:56 +#: kallithea/templates/base/base.html:73 +#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5 +msgid "Repositories" +msgstr "" + +#: kallithea/controllers/home.py:119 +#: 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:125 +msgid "Closed Branches" +msgstr "" + +#: kallithea/controllers/home.py:131 +msgid "Tag" +msgstr "" + +#: kallithea/controllers/home.py:137 +msgid "Bookmark" +msgstr "" + +#: kallithea/controllers/journal.py:146 kallithea/controllers/journal.py:157 +#: kallithea/templates/journal/public_journal.html:4 +#: kallithea/templates/journal/public_journal.html:18 +msgid "Public Journal" +msgstr "" + +#: kallithea/controllers/journal.py:150 kallithea/controllers/journal.py:161 +#: kallithea/templates/base/base.html:290 +#: kallithea/templates/journal/journal.html:5 +#: kallithea/templates/journal/journal.html:13 +msgid "Journal" +msgstr "" + +#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184 +msgid "Bad captcha" +msgstr "" + +#: kallithea/controllers/login.py:145 +#, python-format +msgid "You have successfully registered with %s" +msgstr "" + +#: kallithea/controllers/login.py:189 +msgid "A password reset confirmation code has been sent" +msgstr "" + +#: kallithea/controllers/login.py:236 +msgid "Invalid password reset token" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:157 +#: kallithea/controllers/login.py:241 +msgid "Successfully updated password" +msgstr "" + +#: kallithea/controllers/pullrequests.py:67 +#, python-format +msgid "Invalid reviewer \"%s\" specified" +msgstr "" + +#: kallithea/controllers/pullrequests.py:123 +#, fuzzy, python-format +#| msgid "(closed)" +msgid "%s (closed)" +msgstr "(Zou)" + +#: kallithea/controllers/pullrequests.py:150 +#: kallithea/templates/changeset/changeset.html:12 +msgid "Changeset" +msgstr "" + +#: kallithea/controllers/pullrequests.py:171 +msgid "Special" +msgstr "" + +#: kallithea/controllers/pullrequests.py:172 +msgid "Peer branches" +msgstr "" + +#: kallithea/controllers/pullrequests.py:173 kallithea/model/scm.py:669 +msgid "Bookmarks" +msgstr "" + +#: kallithea/controllers/pullrequests.py:315 +#, python-format +msgid "Error creating pull request: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:342 +#: kallithea/controllers/pullrequests.py:365 +msgid "Error occurred while creating pull request" +msgstr "" + +#: kallithea/controllers/pullrequests.py:347 +msgid "Successfully opened new pull request" +msgstr "" + +#: kallithea/controllers/pullrequests.py:370 +msgid "New pull request iteration created" +msgstr "" + +#: kallithea/controllers/pullrequests.py:398 +#, python-format +msgid "Meanwhile, the following reviewers have been added: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:402 +#, python-format +msgid "Meanwhile, the following reviewers have been removed: %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:418 +#: kallithea/model/pull_request.py:230 +msgid "No description" +msgstr "" + +#: kallithea/controllers/pullrequests.py:427 +msgid "Pull request updated" +msgstr "" + +#: kallithea/controllers/pullrequests.py:440 +msgid "Successfully deleted pull request" +msgstr "" + +#: kallithea/controllers/pullrequests.py:476 +#, python-format +msgid "Revision %s not found in %s" +msgstr "" + +#: kallithea/controllers/pullrequests.py:504 +#, python-format +msgid "Error: changesets not found when displaying pull request from %s." +msgstr "" + +#: kallithea/controllers/pullrequests.py:518 +#, python-format +msgid "This pull request has already been merged to %s." +msgstr "" + +#: kallithea/controllers/pullrequests.py:520 +msgid "This pull request has been closed and can not be updated." +msgstr "" + +#: kallithea/controllers/pullrequests.py:539 +#, python-format +msgid "The following additional changes are available on %s:" +msgstr "" + +#: kallithea/controllers/pullrequests.py:541 +#: kallithea/controllers/pullrequests.py:545 +msgid "No additional changesets found for iterating on this pull request." +msgstr "" + +#: kallithea/controllers/pullrequests.py:553 +#, python-format +msgid "Note: Branch %s has another head: %s." +msgstr "" + +#: kallithea/controllers/pullrequests.py:560 +msgid "Git pull requests don't support iterating yet." +msgstr "" + +#: kallithea/controllers/pullrequests.py:562 +#, python-format +msgid "" +"Error: some changesets not found when displaying pull request from %s." +msgstr "" + +#: kallithea/controllers/pullrequests.py:586 +msgid "The diff can't be shown - the PR revisions could not be found." +msgstr "" + +#: kallithea/controllers/search.py:132 +msgid "Invalid search query. Try quoting it." +msgstr "" + +#: kallithea/controllers/search.py:136 +msgid "The server has no search index." +msgstr "" + +#: kallithea/controllers/search.py:139 +msgid "An error occurred during search operation." +msgstr "" + +#: kallithea/controllers/summary.py:169 +#: kallithea/templates/summary/summary.html:410 +msgid "No data ready yet" +msgstr "" + +#: kallithea/controllers/summary.py:172 +#: kallithea/templates/summary/summary.html:97 +msgid "Statistics are disabled for this repository" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:137 +msgid "Auth settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/auth_settings.py:148 +msgid "error occurred during update of auth settings" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:74 +msgid "Default settings updated successfully" +msgstr "" + +#: kallithea/controllers/admin/defaults.py:89 +msgid "Error occurred during update of defaults" +msgstr "" + +#: kallithea/controllers/admin/gists.py:59 +#: kallithea/controllers/admin/my_account.py:232 +#: kallithea/controllers/admin/users.py:246 +msgid "Forever" +msgstr "" + +#: kallithea/controllers/admin/gists.py:60 +#: kallithea/controllers/admin/my_account.py:233 +#: kallithea/controllers/admin/users.py:247 +msgid "5 minutes" +msgstr "" + +#: kallithea/controllers/admin/gists.py:61 +#: kallithea/controllers/admin/my_account.py:234 +#: kallithea/controllers/admin/users.py:248 +msgid "1 hour" +msgstr "" + +#: kallithea/controllers/admin/gists.py:62 +#: kallithea/controllers/admin/my_account.py:235 +#: kallithea/controllers/admin/users.py:249 +msgid "1 day" +msgstr "" + +#: kallithea/controllers/admin/gists.py:63 +#: kallithea/controllers/admin/my_account.py:236 +#: kallithea/controllers/admin/users.py:250 +msgid "1 month" +msgstr "" + +#: kallithea/controllers/admin/gists.py:67 +#: kallithea/controllers/admin/my_account.py:238 +#: kallithea/controllers/admin/users.py:252 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:65 +#: kallithea/templates/admin/users/user_edit_api_keys.html:65 +msgid "Lifetime" +msgstr "" + +#: kallithea/controllers/admin/gists.py:148 +msgid "Error occurred during gist creation" +msgstr "" + +#: kallithea/controllers/admin/gists.py:164 +#, python-format +msgid "Deleted gist %s" +msgstr "" + +#: kallithea/controllers/admin/gists.py:207 +msgid "Unmodified" +msgstr "" + +#: kallithea/controllers/admin/gists.py:237 +msgid "Successfully updated gist content" +msgstr "" + +#: kallithea/controllers/admin/gists.py:242 +msgid "Successfully updated gist data" +msgstr "" + +#: kallithea/controllers/admin/gists.py:245 +#, python-format +msgid "Error occurred during update of gist %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209 +#: kallithea/model/user.py:230 +msgid "You can't edit this user since it's crucial for entire application" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:119 +msgid "Your account was updated successfully" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:134 +#: kallithea/controllers/admin/users.py:179 +#, python-format +msgid "Error occurred during update of user %s" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:168 +msgid "Error occurred during update of user password" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:209 +#: kallithea/controllers/admin/users.py:365 +#, python-format +msgid "Added email %s to user" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:215 +#: kallithea/controllers/admin/users.py:371 +msgid "An error occurred during email saving" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:224 +#: kallithea/controllers/admin/users.py:381 +msgid "Removed email from user" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:248 +#: kallithea/controllers/admin/users.py:269 +msgid "API key successfully created" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:257 +#: kallithea/controllers/admin/users.py:279 +msgid "API key successfully reset" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:261 +#: kallithea/controllers/admin/users.py:283 +msgid "API key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:281 +#: kallithea/controllers/admin/users.py:454 +#, python-format +msgid "SSH key %s successfully added" +msgstr "" + +#: kallithea/controllers/admin/my_account.py:293 +#: kallithea/controllers/admin/users.py:468 +msgid "SSH key successfully deleted" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:65 +#: kallithea/controllers/admin/permissions.py:69 +#: kallithea/controllers/admin/permissions.py:73 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:8 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8 +#: kallithea/templates/base/perms_summary.html:15 +msgid "Read" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:66 +#: kallithea/controllers/admin/permissions.py:70 +#: kallithea/controllers/admin/permissions.py:74 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9 +#: kallithea/templates/base/perms_summary.html:16 +msgid "Write" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:67 +#: kallithea/controllers/admin/permissions.py:71 +#: kallithea/controllers/admin/permissions.py:75 +#: 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_group_edit_perms.html:10 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47 +#: kallithea/templates/admin/repo_groups/repo_groups.html:9 +#: kallithea/templates/admin/repos/repo_add.html:10 +#: kallithea/templates/admin/repos/repo_add.html:14 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:10 +#: 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_group_edit_perms.html:10 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47 +#: kallithea/templates/admin/user_groups/user_groups.html:9 +#: kallithea/templates/admin/users/user_add.html:8 +#: kallithea/templates/admin/users/user_edit.html:9 +#: kallithea/templates/admin/users/user_edit_profile.html:81 +#: kallithea/templates/admin/users/users.html:9 +#: kallithea/templates/admin/users/users.html:43 +#: kallithea/templates/base/base.html:320 +#: kallithea/templates/base/base.html:321 +#: kallithea/templates/base/base.html:327 +#: kallithea/templates/base/base.html:328 +#: kallithea/templates/base/perms_summary.html:17 +msgid "Admin" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:78 +#: kallithea/controllers/admin/permissions.py:89 +#: kallithea/controllers/admin/permissions.py:94 +#: kallithea/controllers/admin/permissions.py:97 +#: kallithea/controllers/admin/permissions.py:100 +#: kallithea/controllers/admin/permissions.py:103 +#: kallithea/templates/admin/auth/auth_settings.html:42 +#: kallithea/templates/base/root.html:50 +msgid "Disabled" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:80 +msgid "Allowed with manual account activation" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:82 +msgid "Allowed with automatic account activation" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670 +msgid "Manual activation of external account" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671 +msgid "Automatic activation of external account" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:90 +#: kallithea/controllers/admin/permissions.py:93 +#: kallithea/controllers/admin/permissions.py:98 +#: kallithea/controllers/admin/permissions.py:101 +#: kallithea/controllers/admin/permissions.py:104 +#: kallithea/templates/admin/auth/auth_settings.html:42 +#: kallithea/templates/base/root.html:49 +msgid "Enabled" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:127 +msgid "Global permissions updated successfully" +msgstr "" + +#: kallithea/controllers/admin/permissions.py:142 +msgid "Error occurred during update of permissions" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:167 +#, python-format +msgid "Error occurred during creation of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:174 +#, python-format +msgid "Created repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:221 +#, python-format +msgid "Updated repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:237 +#, python-format +msgid "Error occurred during update of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:247 +#, python-format +msgid "This group contains %s repositories and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:254 +#, python-format +msgid "This group contains %s subgroups and cannot be deleted" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:260 +#, python-format +msgid "Removed repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:265 +#, python-format +msgid "Error occurred during deletion of repository group %s" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:349 +#: kallithea/controllers/admin/repo_groups.py:379 +#: kallithea/controllers/admin/user_groups.py:292 +msgid "Cannot revoke permission for yourself as admin" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:364 +msgid "Repository group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repo_groups.py:396 +#: kallithea/controllers/admin/repos.py:358 +#: kallithea/controllers/admin/user_groups.py:304 +msgid "An error occurred during revoking of permission" +msgstr "" + +#: kallithea/controllers/admin/repos.py:136 +#, python-format +msgid "Error creating repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:194 +#, python-format +msgid "Created repository %s from %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:203 +#, python-format +msgid "Forked repository %s as %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:206 +#, python-format +msgid "Created repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:235 +#, python-format +msgid "Repository %s updated successfully" +msgstr "" + +#: kallithea/controllers/admin/repos.py:255 +#, python-format +msgid "Error occurred during update of repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:273 +#, python-format +msgid "Detached %s forks" +msgstr "" + +#: kallithea/controllers/admin/repos.py:276 +#, python-format +msgid "Deleted %s forks" +msgstr "" + +#: kallithea/controllers/admin/repos.py:281 +#, python-format +msgid "Deleted repository %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:284 +#, python-format +msgid "Cannot delete repository %s which still has forks" +msgstr "" + +#: kallithea/controllers/admin/repos.py:289 +#, python-format +msgid "An error occurred during deletion of %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:329 +msgid "Repository permissions updated" +msgstr "" + +#: kallithea/controllers/admin/repos.py:388 +#, python-format +msgid "Field validation error: %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:391 +#, python-format +msgid "An error occurred during creation of field: %r" +msgstr "" + +#: kallithea/controllers/admin/repos.py:402 +msgid "An error occurred during removal of field" +msgstr "" + +#: kallithea/controllers/admin/repos.py:416 +msgid "-- Not a fork --" +msgstr "" + +#: kallithea/controllers/admin/repos.py:448 +msgid "Updated repository visibility in public journal" +msgstr "" + +#: kallithea/controllers/admin/repos.py:452 +msgid "An error occurred during setting this repository in public journal" +msgstr "" + +#: kallithea/controllers/admin/repos.py:468 +msgid "Nothing" +msgstr "" + +#: kallithea/controllers/admin/repos.py:470 +#, python-format +msgid "Marked repository %s as fork of %s" +msgstr "" + +#: kallithea/controllers/admin/repos.py:477 +msgid "An error occurred during this operation" +msgstr "" + +#: kallithea/controllers/admin/repos.py:490 +msgid "Cache invalidation successful" +msgstr "" + +#: kallithea/controllers/admin/repos.py:494 +msgid "An error occurred during cache invalidation" +msgstr "" + +#: kallithea/controllers/admin/repos.py:507 +msgid "Pulled from remote location" +msgstr "" + +#: kallithea/controllers/admin/repos.py:510 +msgid "An error occurred during pull from remote location" +msgstr "" + +#: kallithea/controllers/admin/repos.py:541 +msgid "An error occurred during deletion of repository stats" +msgstr "" + +#: kallithea/controllers/admin/settings.py:131 +msgid "Updated VCS settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238 +msgid "" +"Unable to activate hgsubversion support. The \"hgsubversion\" library is " +"missing" +msgstr "" + +#: kallithea/controllers/admin/settings.py:141 +#: kallithea/controllers/admin/settings.py:233 +msgid "Error occurred while updating application settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:176 +#, python-format +msgid "Repositories successfully rescanned. Added: %s. Removed: %s." +msgstr "" + +#: kallithea/controllers/admin/settings.py:188 +#, python-format +msgid "Invalidated %s repositories" +msgstr "" + +#: kallithea/controllers/admin/settings.py:229 +msgid "Updated application settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:283 +msgid "Updated visualisation settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:288 +msgid "Error occurred during updating visualisation settings" +msgstr "" + +#: kallithea/controllers/admin/settings.py:312 +msgid "Please enter email address" +msgstr "" + +#: kallithea/controllers/admin/settings.py:327 +msgid "Send email task created" +msgstr "" + +#: kallithea/controllers/admin/settings.py:355 +msgid "Hook already exists" +msgstr "" + +#: kallithea/controllers/admin/settings.py:357 +msgid "Builtin hooks are read-only. Please use another hook name." +msgstr "" + +#: kallithea/controllers/admin/settings.py:360 +msgid "Added new hook" +msgstr "" + +#: kallithea/controllers/admin/settings.py:376 +msgid "Updated hooks" +msgstr "" + +#: kallithea/controllers/admin/settings.py:380 +msgid "Error occurred during hook creation" +msgstr "" + +#: kallithea/controllers/admin/settings.py:404 +msgid "Whoosh reindex task scheduled" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:136 +#, python-format +msgid "Created user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:149 +#, python-format +msgid "Error occurred during creation of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:177 +#, python-format +msgid "Updated user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:199 +#, python-format +msgid "Error occurred during update of user group %s" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:210 +msgid "Successfully deleted user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:215 +msgid "An error occurred during deletion of user group" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:271 +msgid "Target group cannot be the same" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:277 +msgid "User group permissions updated" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:386 +#: kallithea/controllers/admin/users.py:336 +msgid "Updated permissions" +msgstr "" + +#: kallithea/controllers/admin/user_groups.py:390 +#: kallithea/controllers/admin/users.py:340 +msgid "An error occurred during permissions saving" +msgstr "" + +#: kallithea/controllers/admin/users.py:121 +#, python-format +msgid "Created user %s" +msgstr "" + +#: kallithea/controllers/admin/users.py:136 +#, python-format +msgid "Error occurred during creation of user %s" +msgstr "" + +#: kallithea/controllers/admin/users.py:160 +msgid "User updated successfully" +msgstr "" + +#: kallithea/controllers/admin/users.py:188 +msgid "Successfully deleted user" +msgstr "" + +#: kallithea/controllers/admin/users.py:193 +msgid "An error occurred during deletion of user" +msgstr "" + +#: kallithea/controllers/admin/users.py:201 +msgid "The default user cannot be edited" +msgstr "" + +#: kallithea/controllers/admin/users.py:407 +#, python-format +msgid "Added IP address %s to user whitelist" +msgstr "" + +#: kallithea/controllers/admin/users.py:413 +msgid "An error occurred while adding IP address" +msgstr "" + +#: kallithea/controllers/admin/users.py:425 +msgid "Removed IP address from user whitelist" +msgstr "" + +#: kallithea/lib/auth.py:668 +msgid "You need to be a registered user to perform this action" +msgstr "" + +#: kallithea/lib/auth.py:696 +msgid "You need to be signed in to view this page" +msgstr "" + +#: kallithea/lib/base.py:483 +msgid "" +"CSRF token leak has been detected - all form tokens have been expired" +msgstr "" + +#: kallithea/lib/base.py:580 +msgid "Repository not found in the filesystem" +msgstr "" + +#: kallithea/lib/base.py:605 +#, python-format +msgid "Changeset for %s %s not found in %s" +msgstr "" + +#: kallithea/lib/base.py:647 +msgid "SSH access is disabled." +msgstr "" + +#: kallithea/lib/diffs.py:194 +msgid "Binary file" +msgstr "" + +#: kallithea/lib/diffs.py:214 +msgid "" +"Changeset was too big and was cut off, use diff menu to display this diff" +msgstr "" + +#: kallithea/lib/diffs.py:223 +msgid "No changes detected" +msgstr "" + +#: kallithea/lib/helpers.py:646 +#, python-format +msgid "Deleted branch: %s" +msgstr "" + +#: kallithea/lib/helpers.py:648 +#, python-format +msgid "Created tag: %s" +msgstr "" + +#: kallithea/lib/helpers.py:659 +#, python-format +msgid "Changeset %s not found" +msgstr "" + +#: kallithea/lib/helpers.py:708 +#, python-format +msgid "Show all combined changesets %s->%s" +msgstr "" + +#: kallithea/lib/helpers.py:714 +msgid "Compare view" +msgstr "" + +#: kallithea/lib/helpers.py:733 +msgid "and" +msgstr "" + +#: kallithea/lib/helpers.py:734 +#, python-format +msgid "%s more" +msgstr "" + +#: kallithea/lib/helpers.py:735 +#: kallithea/templates/changelog/changelog.html:43 +msgid "revisions" +msgstr "" + +#: kallithea/lib/helpers.py:759 +#, python-format +msgid "Fork name %s" +msgstr "" + +#: kallithea/lib/helpers.py:780 +#, python-format +msgid "Pull request %s" +msgstr "" + +#: kallithea/lib/helpers.py:790 +msgid "[deleted] repository" +msgstr "" + +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 +msgid "[created] repository" +msgstr "" + +#: kallithea/lib/helpers.py:794 +msgid "[created] repository as fork" +msgstr "" + +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 +msgid "[forked] repository" +msgstr "" + +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 +msgid "[updated] repository" +msgstr "" + +#: kallithea/lib/helpers.py:800 +msgid "[downloaded] archive from repository" +msgstr "" + +#: kallithea/lib/helpers.py:802 +msgid "[delete] repository" +msgstr "" + +#: kallithea/lib/helpers.py:810 +msgid "[created] user" +msgstr "" + +#: kallithea/lib/helpers.py:812 +msgid "[updated] user" +msgstr "" + +#: kallithea/lib/helpers.py:814 +msgid "[created] user group" +msgstr "" + +#: kallithea/lib/helpers.py:816 +msgid "[updated] user group" +msgstr "" + +#: kallithea/lib/helpers.py:818 +msgid "[commented] on revision in repository" +msgstr "" + +#: kallithea/lib/helpers.py:820 +msgid "[commented] on pull request for" +msgstr "" + +#: kallithea/lib/helpers.py:822 +msgid "[closed] pull request for" +msgstr "" + +#: kallithea/lib/helpers.py:824 +msgid "[pushed] into" +msgstr "" + +#: kallithea/lib/helpers.py:826 +msgid "[committed via Kallithea] into repository" +msgstr "" + +#: kallithea/lib/helpers.py:828 +msgid "[pulled from remote] into repository" +msgstr "" + +#: kallithea/lib/helpers.py:830 +msgid "[pulled] from" +msgstr "" + +#: kallithea/lib/helpers.py:832 +msgid "[started following] repository" +msgstr "" + +#: kallithea/lib/helpers.py:834 +msgid "[stopped following] repository" +msgstr "" + +#: kallithea/lib/helpers.py:954 +#, python-format +msgid " and %s more" +msgstr "" + +#: kallithea/lib/helpers.py:958 +#: kallithea/templates/compare/compare_diff.html:69 +#: kallithea/templates/pullrequests/pullrequest_show.html:297 +msgid "No files" +msgstr "" + +#: kallithea/lib/helpers.py:983 +msgid "new file" +msgstr "" + +#: kallithea/lib/helpers.py:986 +msgid "mod" +msgstr "" + +#: kallithea/lib/helpers.py:989 +msgid "del" +msgstr "" + +#: kallithea/lib/helpers.py:992 +msgid "rename" +msgstr "" + +#: kallithea/lib/helpers.py:997 +msgid "chmod" +msgstr "" + +#: kallithea/lib/helpers.py:1290 +#, 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 "" + +#: kallithea/lib/ssh.py:75 +msgid "SSH key is missing" +msgstr "" + +#: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 +msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" +msgstr "" + +#: kallithea/lib/ssh.py:86 +#, python-format +msgid "Incorrect SSH key - unexpected characters in base64 part %r" +msgstr "" + +#: kallithea/lib/ssh.py:91 +#, python-format +msgid "Incorrect SSH key - failed to decode base64 part %r" +msgstr "" + +#: kallithea/lib/ssh.py:94 +#, python-format +msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" +msgstr "" + +#: kallithea/lib/utils2.py:242 +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/lib/utils2.py:243 +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/lib/utils2.py:244 +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/lib/utils2.py:245 +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/lib/utils2.py:246 +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/lib/utils2.py:247 +#, python-format +msgid "%d second" +msgid_plural "%d seconds" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/lib/utils2.py:263 +#, python-format +msgid "in %s" +msgstr "" + +#: kallithea/lib/utils2.py:265 +#, python-format +msgid "%s ago" +msgstr "" + +#: kallithea/lib/utils2.py:267 +#, python-format +msgid "in %s and %s" +msgstr "" + +#: kallithea/lib/utils2.py:270 +#, python-format +msgid "%s and %s ago" +msgstr "" + +#: kallithea/lib/utils2.py:273 +msgid "just now" +msgstr "" + +#: kallithea/model/comment.py:68 +#, python-format +msgid "on line %s" +msgstr "" + +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 +msgid "[Mention]" +msgstr "" + +#: kallithea/model/db.py:1493 +msgid "top level" +msgstr "" + +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1637 +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1639 +msgid "Default user has admin access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1641 +msgid "Default user has no access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1642 +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1644 +msgid "Default user has admin access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1646 +msgid "Default user has no access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1647 +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1649 +msgid "Default user has admin access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1651 +msgid "Only admins can create repository groups" +msgstr "" + +#: kallithea/model/db.py:1652 +msgid "Non-admins can create repository groups" +msgstr "" + +#: kallithea/model/db.py:1654 +msgid "Only admins can create user groups" +msgstr "" + +#: kallithea/model/db.py:1655 +msgid "Non-admins can create user groups" +msgstr "" + +#: kallithea/model/db.py:1657 +msgid "Only admins can create top level repositories" +msgstr "" + +#: kallithea/model/db.py:1658 +msgid "Non-admins can create top level repositories" +msgstr "" + +#: kallithea/model/db.py:1660 +msgid "" +"Repository creation enabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/db.py:1661 +msgid "" +"Repository creation disabled with write permission to a repository group" +msgstr "" + +#: kallithea/model/db.py:1663 +msgid "Only admins can fork repositories" +msgstr "" + +#: kallithea/model/db.py:1664 +msgid "Non-admins can fork repositories" +msgstr "" + +#: kallithea/model/db.py:1666 +msgid "Registration disabled" +msgstr "" + +#: kallithea/model/db.py:1667 +msgid "User registration with manual account activation" +msgstr "" + +#: kallithea/model/db.py:1668 +msgid "User registration with automatic account activation" +msgstr "" + +#: kallithea/model/db.py:2208 +msgid "Not reviewed" +msgstr "" + +#: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 +msgid "Approved" +msgstr "" + +#: kallithea/model/forms.py:58 +msgid "Please enter a login" +msgstr "" + +#: kallithea/model/forms.py:59 +#, python-format +msgid "Enter a value %(min)i characters long or more" +msgstr "" + +#: kallithea/model/forms.py:67 +msgid "Please enter a password" +msgstr "" + +#: kallithea/model/forms.py:68 +#, python-format +msgid "Enter %(min)i characters or more" +msgstr "" + +#: kallithea/model/forms.py:170 +msgid "Name must not contain only digits" +msgstr "" + +#: kallithea/model/notification.py:163 +#, python-format +msgid "" +"[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " +"%(branch)s" +msgstr "" + +#: kallithea/model/notification.py:166 +#, python-format +msgid "New user %(new_username)s registered" +msgstr "" + +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + +#: kallithea/model/notification.py:169 +#, python-format +msgid "" +"[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + +#: kallithea/model/notification.py:189 +msgid "Closing" +msgstr "" + +#: kallithea/model/pull_request.py:72 +#, python-format +msgid "" +"%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" +msgstr "" + +#: kallithea/model/pull_request.py:207 +msgid "Cannot create empty pull request" +msgstr "" + +#: kallithea/model/pull_request.py:215 +#, python-format +msgid "" +"Cannot create pull request - criss cross merge detected, please merge a " +"later %s revision to %s" +msgstr "" + +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 +msgid "You are not authorized to create the pull request" +msgstr "" + +#: kallithea/model/pull_request.py:337 +msgid "Missing changesets since the previous iteration:" +msgstr "" + +#: kallithea/model/pull_request.py:344 +#, python-format +msgid "New changesets on %s %s since the previous iteration:" +msgstr "" + +#: kallithea/model/pull_request.py:351 +msgid "Ancestor didn't change - diff since previous iteration:" +msgstr "" + +#: kallithea/model/pull_request.py:358 +#, python-format +msgid "" +"This iteration is based on another %s revision and there is no simple " +"diff." +msgstr "" + +#: kallithea/model/pull_request.py:360 +#, python-format +msgid "No changes found on %s %s since previous iteration." +msgstr "" + +#: kallithea/model/pull_request.py:386 +#, python-format +msgid "Closed, next iteration: %s ." +msgstr "" + +#: kallithea/model/scm.py:655 +msgid "latest tip" +msgstr "" + +#: kallithea/model/ssh_key.py:57 +#, python-format +msgid "SSH key %r is invalid: %s" +msgstr "" + +#: kallithea/model/ssh_key.py:69 +#, python-format +msgid "SSH key %s is already used by %s" +msgstr "" + +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 +msgid "New user registration" +msgstr "" + +#: kallithea/model/user.py:248 +msgid "" +"You can't remove this user since it is crucial for the entire application" +msgstr "" + +#: kallithea/model/user.py:253 +#, python-format +msgid "" +"User \"%s\" still owns %s repositories and cannot be removed. Switch " +"owners or remove those repositories: %s" +msgstr "" + +#: kallithea/model/user.py:258 +#, python-format +msgid "" +"User \"%s\" still owns %s repository groups and cannot be removed. Switch " +"owners or remove those repository groups: %s" +msgstr "" + +#: kallithea/model/user.py:265 +#, python-format +msgid "" +"User \"%s\" still owns %s user groups and cannot be removed. Switch " +"owners or remove those user groups: %s" +msgstr "" + +#: kallithea/model/user.py:359 +msgid "Password reset link" +msgstr "" + +#: kallithea/model/user.py:406 +msgid "Password reset notification" +msgstr "" + +#: kallithea/model/user.py:407 +#, python-format +msgid "" +"The password to your account %s has been changed using password reset " +"form." +msgstr "" + +#: kallithea/model/validators.py:52 kallithea/model/validators.py:53 +msgid "Value cannot be an empty list" +msgstr "" + +#: kallithea/model/validators.py:72 +#, python-format +msgid "Username \"%(username)s\" already exists" +msgstr "" + +#: kallithea/model/validators.py:74 +#, python-format +msgid "Username \"%(username)s\" cannot be used" +msgstr "" + +#: kallithea/model/validators.py:76 +msgid "" +"Username may only contain alphanumeric characters underscores, periods or " +"dashes and must begin with an alphanumeric character or underscore" +msgstr "" + +#: kallithea/model/validators.py:103 +msgid "The input is not valid" +msgstr "" + +#: kallithea/model/validators.py:110 +#, python-format +msgid "Username %(username)s is not valid" +msgstr "" + +#: kallithea/model/validators.py:131 +msgid "Invalid user group name" +msgstr "" + +#: kallithea/model/validators.py:132 +#, python-format +msgid "User group \"%(usergroup)s\" already exists" +msgstr "" + +#: kallithea/model/validators.py:134 +msgid "" +"user group name may only contain alphanumeric characters underscores, " +"periods or dashes and must begin with alphanumeric character" +msgstr "" + +#: kallithea/model/validators.py:174 +msgid "Cannot assign this group as parent" +msgstr "" + +#: kallithea/model/validators.py:175 +#, python-format +msgid "Group \"%(group_name)s\" already exists" +msgstr "" + +#: kallithea/model/validators.py:177 +#, python-format +msgid "Repository with name \"%(group_name)s\" already exists" +msgstr "" + +#: kallithea/model/validators.py:233 +msgid "Invalid characters (non-ascii) in password" +msgstr "" + +#: kallithea/model/validators.py:248 +msgid "Invalid old password" +msgstr "" + +#: kallithea/model/validators.py:264 +msgid "Passwords do not match" +msgstr "" + +#: kallithea/model/validators.py:279 +msgid "Invalid username or password" +msgstr "" + +#: kallithea/model/validators.py:313 +#, python-format +msgid "Repository name %(repo)s is not allowed" +msgstr "" + +#: kallithea/model/validators.py:315 +#, python-format +msgid "Repository named %(repo)s already exists" +msgstr "" + +#: kallithea/model/validators.py:316 +#, python-format +msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\"" +msgstr "" + +#: kallithea/model/validators.py:318 +#, python-format +msgid "Repository group with name \"%(repo)s\" already exists" +msgstr "" + +#: kallithea/model/validators.py:404 +msgid "Invalid repository URL" +msgstr "" + +#: kallithea/model/validators.py:405 +msgid "" +"Invalid repository URL. It must be a valid http, https, ssh, svn+http or " +"svn+https URL" +msgstr "" + +#: kallithea/model/validators.py:430 +msgid "Fork has to be the same type as parent" +msgstr "" + +#: kallithea/model/validators.py:445 +msgid "You don't have permissions to create repository in this group" +msgstr "" + +#: kallithea/model/validators.py:447 +msgid "no permission to create repository in root location" +msgstr "" + +#: kallithea/model/validators.py:497 +msgid "You don't have permissions to create a group in this location" +msgstr "" + +#: kallithea/model/validators.py:537 +msgid "This username or user group name is not valid" +msgstr "" + +#: kallithea/model/validators.py:630 +msgid "This is not a valid path" +msgstr "" + +#: kallithea/model/validators.py:647 +msgid "This email address is already in use" +msgstr "" + +#: kallithea/model/validators.py:667 +#, python-format +msgid "Email address \"%(email)s\" not found" +msgstr "" + +#: kallithea/model/validators.py:704 +msgid "" +"The LDAP Login attribute of the CN must be specified - this is the name " +"of the attribute that is equivalent to \"username\"" +msgstr "" + +#: kallithea/model/validators.py:716 +msgid "Please enter a valid IPv4 or IPv6 address" +msgstr "" + +#: kallithea/model/validators.py:717 +#, python-format +msgid "" +"The network size (bits) must be within the range of 0-32 (not %(bits)r)" +msgstr "" + +#: kallithea/model/validators.py:750 +msgid "Key name can only consist of letters, underscore, dash or numbers" +msgstr "" + +#: kallithea/model/validators.py:764 +msgid "Filename cannot be inside a directory" +msgstr "" + +#: kallithea/model/validators.py:780 +#, 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:13 +msgid "About" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add.html:5 +#: kallithea/templates/admin/repos/repo_add.html:19 +#: kallithea/templates/admin/repos/repos.html:23 +#: kallithea/templates/index_base.html:25 +#: kallithea/templates/index_base.html:30 +msgid "Add Repository" +msgstr "" + +#: 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:25 +#: kallithea/templates/index_base.html:27 +#: kallithea/templates/index_base.html:32 +msgid "Add Repository Group" +msgstr "" + +#: kallithea/templates/index_base.html:37 +msgid "You have admin right to this group, and can edit it" +msgstr "" + +#: kallithea/templates/index_base.html:37 +msgid "Edit Repository Group" +msgstr "" + +#: kallithea/templates/admin/admin_log.html:7 +#: kallithea/templates/admin/permissions/permissions_globals.html:14 +#: kallithea/templates/index_base.html:53 +msgid "Repository" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:59 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:61 +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5 +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58 +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:35 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12 +#: kallithea/templates/admin/repo_groups/repo_groups.html:40 +#: kallithea/templates/admin/repos/repo_add_base.html:21 +#: kallithea/templates/admin/repos/repo_edit_settings.html:54 +#: kallithea/templates/admin/repos/repos.html:39 +#: kallithea/templates/admin/user_groups/user_group_add.html:33 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10 +#: kallithea/templates/admin/user_groups/user_groups.html:39 +#: kallithea/templates/admin/users/user_edit_api_keys.html:59 +#: kallithea/templates/admin/users/user_edit_api_keys.html:61 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:60 +#: kallithea/templates/email_templates/pull_request.html:37 +#: kallithea/templates/forks/fork.html:34 +#: kallithea/templates/index_base.html:58 +#: kallithea/templates/pullrequests/pullrequest.html:33 +#: kallithea/templates/pullrequests/pullrequest_show.html:38 +#: kallithea/templates/pullrequests/pullrequest_show.html:59 +#: kallithea/templates/summary/summary.html:87 +msgid "Description" +msgstr "" + +#: kallithea/templates/index_base.html:60 +msgid "Last Change" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_repos.html:15 +#: kallithea/templates/admin/my_account/my_account_watched.html:15 +#: kallithea/templates/admin/repos/repos.html:41 +#: kallithea/templates/index_base.html:62 +msgid "Tip" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10 +#: kallithea/templates/admin/repo_groups/repo_groups.html:42 +#: kallithea/templates/admin/repos/repo_edit_settings.html:47 +#: kallithea/templates/admin/repos/repos.html:42 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8 +#: kallithea/templates/admin/user_groups/user_groups.html:42 +#: kallithea/templates/index_base.html:63 +#: kallithea/templates/pullrequests/pullrequest_data.html:16 +#: kallithea/templates/pullrequests/pullrequest_show.html:124 +#: kallithea/templates/pullrequests/pullrequest_show.html:219 +#: kallithea/templates/summary/summary.html:132 +msgid "Owner" +msgstr "" + +#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5 +#: kallithea/templates/login.html:19 +msgid "Log In" +msgstr "" + +#: kallithea/templates/login.html:17 +#, python-format +msgid "Log In to %s" +msgstr "" + +#: kallithea/templates/admin/admin_log.html:5 +#: kallithea/templates/admin/my_account/my_account_profile.html:18 +#: kallithea/templates/admin/users/user_add.html:27 +#: kallithea/templates/admin/users/user_edit_profile.html:18 +#: kallithea/templates/admin/users/users.html:37 +#: kallithea/templates/base/base.html:364 +#: kallithea/templates/email_templates/registration.html:11 +#: kallithea/templates/login.html:28 kallithea/templates/register.html:31 +msgid "Username" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:27 +#: kallithea/templates/admin/users/user_add.html:34 +#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34 +#: kallithea/templates/register.html:38 +msgid "Password" +msgstr "" + +#: kallithea/templates/login.html:44 +msgid "Stay logged in after browser restart" +msgstr "" + +#: kallithea/templates/login.html:52 +msgid "Forgot your password ?" +msgstr "" + +#: kallithea/templates/login.html:55 +msgid "Don't have an account ?" +msgstr "" + +#: kallithea/templates/login.html:62 +msgid "Sign In" +msgstr "" + +#: kallithea/templates/password_reset.html:5 +msgid "Password Reset" +msgstr "" + +#: kallithea/templates/password_reset.html:21 +#: kallithea/templates/password_reset_confirmation.html:16 +#, python-format +msgid "Reset Your Password to %s" +msgstr "" + +#: kallithea/templates/password_reset.html:23 +#: kallithea/templates/password_reset_confirmation.html:5 +#: kallithea/templates/password_reset_confirmation.html:18 +msgid "Reset Your Password" +msgstr "" + +#: kallithea/templates/password_reset.html:30 +msgid "Email Address" +msgstr "" + +#: kallithea/templates/password_reset.html:38 +#: kallithea/templates/register.html:74 +msgid "Captcha" +msgstr "" + +#: kallithea/templates/password_reset.html:47 +msgid "Send Password Reset Email" +msgstr "" + +#: kallithea/templates/password_reset.html:52 +msgid "" +"A password reset link will be sent to the specified email address if it " +"is registered in the system." +msgstr "" + +#: kallithea/templates/password_reset_confirmation.html:23 +#, python-format +msgid "You are about to set a new password for the email address %s." +msgstr "" + +#: kallithea/templates/password_reset_confirmation.html:24 +msgid "" +"Note that you must use the same browser session for this as the one used " +"to request the password reset." +msgstr "" + +#: kallithea/templates/password_reset_confirmation.html:29 +msgid "Code you received in the email" +msgstr "" + +#: kallithea/templates/password_reset_confirmation.html:36 +msgid "New Password" +msgstr "" + +#: kallithea/templates/password_reset_confirmation.html:43 +msgid "Confirm New Password" +msgstr "" + +#: kallithea/templates/password_reset_confirmation.html:51 +msgid "Confirm" +msgstr "" + +#: kallithea/templates/register.html:5 kallithea/templates/register.html:24 +#: kallithea/templates/register.html:83 +msgid "Sign Up" +msgstr "" + +#: kallithea/templates/register.html:22 +#, python-format +msgid "Sign Up to %s" +msgstr "" + +#: kallithea/templates/register.html:45 +msgid "Re-enter password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:25 +#: kallithea/templates/admin/users/user_add.html:48 +#: kallithea/templates/admin/users/user_edit_profile.html:60 +#: kallithea/templates/admin/users/users.html:38 +#: kallithea/templates/register.html:52 +msgid "First Name" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:32 +#: kallithea/templates/admin/users/user_add.html:55 +#: kallithea/templates/admin/users/user_edit_profile.html:67 +#: kallithea/templates/admin/users/users.html:39 +#: kallithea/templates/register.html:59 +msgid "Last Name" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:39 +#: kallithea/templates/admin/settings/settings.html:31 +#: kallithea/templates/admin/users/user_add.html:62 +#: kallithea/templates/admin/users/user_edit_profile.html:25 +#: kallithea/templates/email_templates/registration.html:33 +#: kallithea/templates/register.html:66 +msgid "Email" +msgstr "" + +#: kallithea/templates/register.html:85 +msgid "Registered accounts are ready to use and need no further action." +msgstr "" + +#: kallithea/templates/register.html:87 +msgid "Please wait for an administrator to activate your account." +msgstr "" + +#: kallithea/templates/admin/admin.html:5 +#: kallithea/templates/admin/admin.html:13 +#: kallithea/templates/base/base.html:55 +msgid "Admin Journal" +msgstr "" + +#: kallithea/templates/admin/admin.html:10 +#: kallithea/templates/journal/journal.html:10 +msgid "journal filter..." +msgstr "" + +#: kallithea/templates/admin/admin.html:12 +#: kallithea/templates/journal/journal.html:12 +msgid "Filter" +msgstr "" + +#: kallithea/templates/admin/admin.html:13 +#: kallithea/templates/journal/journal.html:13 +#, python-format +msgid "%s Entry" +msgid_plural "%s Entries" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/admin_log.html:6 +#: kallithea/templates/admin/my_account/my_account_repos.html:16 +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7 +#: kallithea/templates/admin/repo_groups/repo_groups.html:43 +#: kallithea/templates/admin/repos/repo_edit_fields.html:9 +#: kallithea/templates/admin/repos/repos.html:44 +#: kallithea/templates/admin/user_groups/user_groups.html:43 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7 +#: kallithea/templates/admin/users/users.html:45 +msgid "Action" +msgstr "" + +#: kallithea/templates/admin/admin_log.html:8 +msgid "Date" +msgstr "" + +#: kallithea/templates/admin/admin_log.html:9 +msgid "From IP" +msgstr "" + +#: kallithea/templates/admin/admin_log.html:61 +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:61 +msgid "Authentication" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:27 +msgid "Authentication Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:29 +msgid "Enabled Plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:32 +msgid "" +"Comma-separated list of plugins; Kallithea will try user authentication " +"in plugin order" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:36 +msgid "Available built-in plugins" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:53 +msgid "Plugin" +msgstr "" + +#: kallithea/templates/admin/auth/auth_settings.html:101 +#: kallithea/templates/admin/defaults/defaults.html:59 +#: kallithea/templates/admin/my_account/my_account_password.html:30 +#: kallithea/templates/admin/my_account/my_account_profile.html:47 +#: kallithea/templates/admin/permissions/permissions_globals.html:95 +#: kallithea/templates/admin/repo_groups/repo_group_add.html:58 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:84 +#: kallithea/templates/admin/repos/repo_edit_settings.html:99 +#: kallithea/templates/admin/settings/settings_hooks.html:46 +#: kallithea/templates/admin/user_groups/user_group_add.html:48 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46 +#: kallithea/templates/admin/users/user_add.html:80 +#: kallithea/templates/admin/users/user_edit_profile.html:89 +#: kallithea/templates/base/default_perms_box.html:42 +msgid "Save" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:5 +#: kallithea/templates/admin/defaults/defaults.html:11 +#: kallithea/templates/base/base.html:62 +msgid "Repository Defaults" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:27 +#: kallithea/templates/admin/repos/repo_add_base.html:42 +#: kallithea/templates/admin/repos/repo_edit_fields.html:8 +msgid "Type" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:34 +#: kallithea/templates/admin/repos/repo_add_base.html:56 +#: kallithea/templates/admin/repos/repo_edit_settings.html:62 +#: kallithea/templates/data_table/_dt_elements.html:21 +msgid "Private repository" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:37 +#: kallithea/templates/admin/repos/repo_add_base.html:59 +#: kallithea/templates/admin/repos/repo_edit_settings.html:65 +#: kallithea/templates/forks/fork.html:61 +msgid "" +"Private repositories are only visible to people explicitly added as " +"collaborators." +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:42 +#: kallithea/templates/admin/repos/repo_edit_settings.html:69 +msgid "Enable statistics" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:45 +#: kallithea/templates/admin/repos/repo_edit_settings.html:72 +msgid "Enable statistics window on summary page." +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:50 +#: kallithea/templates/admin/repos/repo_edit_settings.html:76 +msgid "Enable downloads" +msgstr "" + +#: kallithea/templates/admin/defaults/defaults.html:53 +#: kallithea/templates/admin/repos/repo_edit_settings.html:79 +msgid "Enable download menu on summary page." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:5 +#: kallithea/templates/admin/gists/edit.html:18 +msgid "Edit Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:35 +#, python-format +msgid "" +"Gist was updated since you started editing. Copy your changes and click " +"%(here)s to reload new version." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:36 +msgid "here" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:51 +#: kallithea/templates/admin/gists/new.html:35 +msgid "Gist description ..." +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:54 +#: kallithea/templates/admin/gists/new.html:38 +msgid "Gist lifetime" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/edit.html:61 +#: kallithea/templates/admin/gists/index.html:54 +#: kallithea/templates/admin/gists/index.html:56 +#: kallithea/templates/admin/gists/show.html:45 +#: kallithea/templates/admin/gists/show.html:47 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:7 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:26 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:31 +#: kallithea/templates/admin/users/user_edit_api_keys.html:7 +#: kallithea/templates/admin/users/user_edit_api_keys.html:26 +#: kallithea/templates/admin/users/user_edit_api_keys.html:31 +msgid "Expires" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:59 +#: kallithea/templates/admin/gists/index.html:54 +#: kallithea/templates/admin/gists/show.html:45 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:7 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:26 +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21 +#: kallithea/templates/admin/users/user_edit_api_keys.html:7 +#: kallithea/templates/admin/users/user_edit_api_keys.html:26 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21 +msgid "Never" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:145 +msgid "Update Gist" +msgstr "" + +#: kallithea/templates/admin/gists/edit.html:146 +#: kallithea/templates/base/root.html:27 +#: kallithea/templates/changeset/changeset_file_comment.html:130 +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 "" + +#: kallithea/templates/admin/gists/index.html:8 +#: kallithea/templates/admin/gists/index.html:18 +#, python-format +msgid "Public Gists for User %s" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:10 +#: kallithea/templates/admin/gists/index.html:20 +msgid "Public Gists" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:37 +#: kallithea/templates/admin/gists/show.html:25 +#: kallithea/templates/base/base.html:305 +msgid "Create New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:51 +#: kallithea/templates/data_table/_dt_elements.html:78 +msgid "Created" +msgstr "" + +#: kallithea/templates/admin/gists/index.html:66 +#, fuzzy +#| msgid "There are no changesets yet" +msgid "There are no gists yet" +msgstr "Et sinn nach keng Ännerungen do" + +#: kallithea/templates/admin/gists/new.html:5 +#: kallithea/templates/admin/gists/new.html:18 +msgid "New Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:45 +msgid "Name this gist ..." +msgstr "" + +#: kallithea/templates/admin/gists/new.html:53 +msgid "Create Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:54 +msgid "Create Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/new.html:55 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:14 +#: kallithea/templates/admin/my_account/my_account_api_keys.html:73 +#: kallithea/templates/admin/my_account/my_account_emails.html:47 +#: kallithea/templates/admin/my_account/my_account_password.html:31 +#: kallithea/templates/admin/my_account/my_account_profile.html:48 +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66 +#: kallithea/templates/admin/permissions/permissions_globals.html:96 +#: kallithea/templates/admin/permissions/permissions_ips.html:34 +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28 +#: kallithea/templates/admin/repos/repo_edit_fields.html:54 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:85 +#: kallithea/templates/admin/repos/repo_edit_settings.html:100 +#: kallithea/templates/admin/settings/settings_global.html:50 +#: kallithea/templates/admin/settings/settings_vcs.html:66 +#: kallithea/templates/admin/settings/settings_visual.html:129 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 +#: kallithea/templates/admin/users/user_edit_api_keys.html:14 +#: kallithea/templates/admin/users/user_edit_api_keys.html:73 +#: kallithea/templates/admin/users/user_edit_emails.html:47 +#: kallithea/templates/admin/users/user_edit_ips.html:45 +#: kallithea/templates/admin/users/user_edit_profile.html:90 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66 +#: kallithea/templates/base/default_perms_box.html:43 +#: kallithea/templates/files/files_add.html:69 +#: kallithea/templates/files/files_delete.html:41 +#: kallithea/templates/files/files_edit.html:72 +#: kallithea/templates/pullrequests/pullrequest.html:78 +msgid "Reset" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:5 +#: kallithea/templates/admin/gists/show.html:9 +msgid "Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:10 +msgid "URL" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:35 +msgid "Public Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:37 +msgid "Private Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:54 +#: kallithea/templates/admin/my_account/my_account_emails.html:23 +#: kallithea/templates/admin/permissions/permissions_ips.html:11 +#: kallithea/templates/admin/repos/repo_edit_advanced.html:42 +#: kallithea/templates/admin/repos/repo_edit_fields.html:19 +#: kallithea/templates/admin/settings/settings_hooks.html:30 +#: kallithea/templates/admin/users/user_edit_emails.html:23 +#: kallithea/templates/admin/users/user_edit_ips.html:21 +#: kallithea/templates/changeset/changeset_file_comment.html:30 +#: kallithea/templates/changeset/changeset_file_comment.html:121 +#: kallithea/templates/data_table/_dt_elements.html:69 +#: kallithea/templates/data_table/_dt_elements.html:89 +#: kallithea/templates/data_table/_dt_elements.html:91 +#: kallithea/templates/data_table/_dt_elements.html:101 +#: kallithea/templates/data_table/_dt_elements.html:103 +#: kallithea/templates/data_table/_dt_elements.html:120 +#: kallithea/templates/data_table/_dt_elements.html:122 +#: kallithea/templates/files/files_source.html:35 +#: kallithea/templates/files/files_source.html:38 +#: kallithea/templates/files/files_source.html:41 +#: kallithea/templates/pullrequests/pullrequest_data.html:20 +msgid "Delete" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:54 +msgid "Confirm to delete this Gist" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:61 +#: kallithea/templates/base/perms_summary.html:44 +#: kallithea/templates/base/perms_summary.html:81 +#: kallithea/templates/base/perms_summary.html:83 +#: kallithea/templates/data_table/_dt_elements.html:63 +#: kallithea/templates/data_table/_dt_elements.html:64 +#: kallithea/templates/data_table/_dt_elements.html:85 +#: kallithea/templates/data_table/_dt_elements.html:86 +#: kallithea/templates/data_table/_dt_elements.html:97 +#: kallithea/templates/data_table/_dt_elements.html:98 +#: kallithea/templates/data_table/_dt_elements.html:116 +#: kallithea/templates/data_table/_dt_elements.html:117 +#: kallithea/templates/files/diff_2way.html:56 +#: kallithea/templates/files/files_source.html:37 +#: kallithea/templates/files/files_source.html:40 +#: kallithea/templates/pullrequests/pullrequest_show.html:41 +msgid "Edit" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:63 +#: kallithea/templates/files/files_edit.html:52 +#: kallithea/templates/files/files_source.html:30 +msgid "Show as Raw" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:69 +msgid "created" +msgstr "" + +#: kallithea/templates/admin/gists/show.html:82 +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:390 +msgid "My Account" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:25 +#: kallithea/templates/admin/users/user_edit.html:29 +msgid "Profile" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:26 +msgid "Email Addresses" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:29 +#: kallithea/templates/admin/users/user_edit.html:32 +msgid "SSH Keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:31 +#: kallithea/templates/admin/users/user_edit.html:34 +msgid "API Keys" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:32 +msgid "Owned Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:33 +#: kallithea/templates/journal/journal.html:33 +msgid "Watched Repositories" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account.html:34 +#: kallithea/templates/admin/permissions/permissions.html:30 +#: kallithea/templates/admin/user_groups/user_group_edit.html:32 +#: kallithea/templates/admin/users/user_edit.html:37 +msgid "Show Permissions" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:5 +#: kallithea/templates/admin/users/user_edit_api_keys.html:5 +msgid "Built-in" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:13 +#: kallithea/templates/admin/users/user_edit_api_keys.html:13 +#, python-format +msgid "Confirm to reset this API key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:29 +#: kallithea/templates/admin/users/user_edit_api_keys.html:29 +msgid "Expired" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:39 +#: kallithea/templates/admin/users/user_edit_api_keys.html:39 +#, python-format +msgid "Confirm to remove this API key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:41 +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30 +#: kallithea/templates/admin/users/user_edit_api_keys.html:41 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30 +msgid "Remove" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:48 +#: kallithea/templates/admin/users/user_edit_api_keys.html:48 +msgid "No additional API keys specified" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:56 +#: kallithea/templates/admin/users/user_edit_api_keys.html:56 +msgid "New API key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:72 +#: kallithea/templates/admin/my_account/my_account_emails.html:46 +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65 +#: kallithea/templates/admin/permissions/permissions_ips.html:33 +#: kallithea/templates/admin/repos/repo_add_base.html:64 +#: kallithea/templates/admin/repos/repo_edit_fields.html:53 +#: kallithea/templates/admin/users/user_edit_api_keys.html:72 +#: kallithea/templates/admin/users/user_edit_emails.html:46 +#: kallithea/templates/admin/users/user_edit_ips.html:44 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65 +msgid "Add" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:81 +#, python-format +msgid "" +"\n" +"API keys are used to let scripts or services access %s using your\n" +"account, as if you had provided the script or service with your actual\n" +"password.\n" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_api_keys.html:86 +msgid "" +"\n" +"Like passwords, API keys should therefore never be shared with others,\n" +"nor passed to untrusted scripts or services. If such sharing should\n" +"happen anyway, reset the API key on this page to prevent further use.\n" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:9 +#: kallithea/templates/admin/users/user_edit_emails.html:9 +msgid "Primary" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:24 +#: kallithea/templates/admin/users/user_edit_emails.html:24 +#, python-format +msgid "Confirm to delete this email: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:30 +#: kallithea/templates/admin/users/user_edit_emails.html:30 +msgid "No additional emails specified." +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_emails.html:39 +#: kallithea/templates/admin/users/user_edit_emails.html:39 +msgid "New email address" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:1 +msgid "Change Your Account Password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:8 +msgid "Current password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:15 +#: kallithea/templates/admin/users/user_edit_profile.html:46 +msgid "New password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:22 +msgid "Confirm new password" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_password.html:39 +#, python-format +msgid "" +"This account is managed with %s and the password cannot be changed here" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_perms.html:3 +msgid "Current IP" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:4 +#: kallithea/templates/admin/users/user_edit_profile.html:4 +msgid "Gravatar" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:10 +#: kallithea/templates/admin/users/user_edit_profile.html:10 +#, python-format +msgid "Change %s avatar at" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_profile.html:12 +#: kallithea/templates/admin/users/user_edit_profile.html:12 +msgid "Avatars are disabled" +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:13 +#: kallithea/templates/admin/my_account/my_account_watched.html:13 +#: kallithea/templates/admin/repo_groups/repo_groups.html:39 +#: kallithea/templates/admin/repos/repo_add_base.html:6 +#: kallithea/templates/admin/repos/repo_edit_settings.html:4 +#: kallithea/templates/admin/repos/repos.html:38 +#: kallithea/templates/admin/user_groups/user_groups.html:38 +#: kallithea/templates/base/perms_summary.html:54 +#: kallithea/templates/files/files_browser.html:54 +msgid "Name" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4 +msgid "Fingerprint" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6 +msgid "Last Used" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28 +#, python-format +msgid "Confirm to remove this SSH key: %s" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39 +msgid "No SSH keys have been added" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49 +msgid "New SSH key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52 +msgid "Public key" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54 +#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54 +msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)" +msgstr "" + +#: kallithea/templates/admin/my_account/my_account_watched.html:1 +msgid "Repositories You are Watching" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions.html:5 +#: kallithea/templates/admin/permissions/permissions.html:11 +#: kallithea/templates/base/base.html:60 +msgid "Default 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:35 +msgid "IP Whitelist" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:4 +msgid "Anonymous access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:8 +msgid "Allow anonymous access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:10 +#, 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:19 +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:20 +msgid "Apply to all existing repositories" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:23 +msgid "Permissions for the Default user on new repositories." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:27 +#: kallithea/templates/admin/repos/repo_add_base.html:28 +#: kallithea/templates/admin/repos/repo_edit_settings.html:33 +#: kallithea/templates/data_table/_dt_elements.html:134 +#: kallithea/templates/forks/fork.html:42 +msgid "Repository group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:32 +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:33 +msgid "Apply to all existing repository groups" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:36 +msgid "Permissions for the Default user on new repository groups." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:40 +#: kallithea/templates/data_table/_dt_elements.html:141 +msgid "User group" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:45 +msgid "" +"All default permissions on each user group will be reset to chosen " +"permission, note that all custom default permission on user groups will " +"be lost" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:46 +msgid "Apply to all existing user groups" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:49 +msgid "Permissions for the Default user on new user groups." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:53 +msgid "Top level repository creation" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:56 +msgid "" +"Enable this to allow non-admins to create repositories at the top level." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:57 +msgid "" +"Note: This will also give all users API access to create repositories " +"everywhere. That might change in future versions." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:61 +msgid "Repository creation with group write access" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:64 +msgid "" +"With this, write permission to a repository group allows creating " +"repositories inside that group. Without this, group write permissions " +"mean nothing." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:68 +msgid "User group creation" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:71 +msgid "Enable this to allow non-admins to create user groups." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:75 +msgid "Repository forking" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:78 +msgid "Enable this to allow non-admins to fork repositories." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:82 +msgid "Registration" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_globals.html:88 +msgid "External auth account activation" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:12 +#: kallithea/templates/admin/users/user_edit_ips.html:22 +#, python-format +msgid "Confirm to delete this IP address: %s" +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:18 +#: kallithea/templates/admin/users/user_edit_ips.html:29 +msgid "All IP addresses are allowed." +msgstr "" + +#: kallithea/templates/admin/permissions/permissions_ips.html:25 +#: kallithea/templates/admin/users/user_edit_ips.html:37 +msgid "New IP address" +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:89 +#: kallithea/templates/admin/repo_groups/repo_groups.html:9 +#: kallithea/templates/base/base.html:57 +#: kallithea/templates/base/base.html:76 +msgid "Repository Groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:28 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:5 +#: kallithea/templates/admin/user_groups/user_group_add.html:27 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:4 +msgid "Group name" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:42 +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:19 +msgid "Group parent" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:49 +#: kallithea/templates/admin/repos/repo_add_base.html:35 +msgid "Copy parent group permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_add.html:52 +#: kallithea/templates/admin/repos/repo_add_base.html:38 +msgid "Copy permission set from parent repository group." +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5 +#, python-format +msgid "%s Repository Group Settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:29 +msgid "Add Child Group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:36 +#: kallithea/templates/admin/repos/repo_edit.html:12 +#: kallithea/templates/admin/repos/repo_edit.html:25 +#: kallithea/templates/admin/settings/settings.html:11 +#: kallithea/templates/admin/user_groups/user_group_edit.html:29 +#: kallithea/templates/base/base.html:63 +#: kallithea/templates/base/base.html:152 +msgid "Settings" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:37 +#: kallithea/templates/admin/repos/repo_edit.html:31 +#: kallithea/templates/admin/user_groups/user_group_edit.html:30 +#: kallithea/templates/admin/users/user_edit.html:36 +msgid "Advanced" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit.html:38 +#: kallithea/templates/admin/repos/repo_edit.html:28 +#: kallithea/templates/admin/user_groups/user_group_edit.html:31 +msgid "Permissions" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1 +#, python-format +msgid "Repository Group: %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6 +msgid "Top level repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7 +msgid "Total repositories" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8 +msgid "Children groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9 +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7 +#: kallithea/templates/admin/users/user_edit_advanced.html:8 +#: kallithea/templates/pullrequests/pullrequest_show.html:118 +msgid "Created on" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21 +#: kallithea/templates/data_table/_dt_elements.html:121 +#, python-format +msgid "Confirm to delete this group: %s with %s repository" +msgid_plural "Confirm to delete this group: %s with %s repositories" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25 +msgid "Delete this repository group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 +msgid "Not visible" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8 +msgid "Visible" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9 +msgid "Add repos" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10 +msgid "Add/Edit groups" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:11 +#: 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:23 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:36 +#: 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:42 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:67 +#: 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:81 +#: kallithea/templates/admin/repos/repo_edit_permissions.html:77 +#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:81 +msgid "Add new" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:87 +msgid "Apply to children" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:91 +msgid "Both" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:92 +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 "Remove this group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38 +msgid "Confirm to delete this group" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_group_show.html:4 +#, python-format +msgid "Repository group %s" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:5 +msgid "Repository Groups Administration" +msgstr "" + +#: kallithea/templates/admin/repo_groups/repo_groups.html:41 +msgid "Number of Top-level Repositories" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:12 +msgid "Clone remote repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:16 +msgid "" +"Optional: URL of a remote repository. If set, the repository will be " +"created as a clone from this URL." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:24 +#: kallithea/templates/admin/repos/repo_edit_settings.html:57 +#: kallithea/templates/forks/fork.html:37 +msgid "" +"Keep it short and to the point. Use a README file for longer descriptions." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:31 +#: kallithea/templates/admin/repos/repo_edit_settings.html:36 +#: kallithea/templates/forks/fork.html:45 +msgid "Optionally select a group to put this repository into." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:45 +msgid "Type of repository to create." +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:49 +#: kallithea/templates/admin/repos/repo_edit_settings.html:40 +#: kallithea/templates/forks/fork.html:50 +msgid "Landing revision" +msgstr "" + +#: kallithea/templates/admin/repos/repo_add_base.html:52 +msgid "" +"Default revision for files page, downloads, full text search index and " +"readme generation" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html:9 +#, python-format +msgid "%s Creating Repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_creating.html: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 "" + +#: kallithea/templates/admin/repos/repo_edit.html:34 +msgid "Extra Fields" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:37 +msgid "Caches" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:40 +msgid "Remote" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit.html:43 +#: kallithea/templates/summary/statistics.html:8 +#: kallithea/templates/summary/summary.html:169 +#: kallithea/templates/summary/summary.html:170 +msgid "Statistics" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:1 +msgid "Parent" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:5 +msgid "Set" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:7 +msgid "Manually set this repository as a fork of another from the list." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:20 +msgid "Public Journal Visibility" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:27 +msgid "Remove from public journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:32 +msgid "Add to Public Journal" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:37 +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:46 +#: kallithea/templates/data_table/_dt_elements.html:68 +#, python-format +msgid "Confirm to delete this repository: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:48 +msgid "Delete this Repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:51 +#, python-format +msgid "This repository has %s fork" +msgid_plural "This repository has %s forks" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:54 +msgid "Detach forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:58 +msgid "Delete forks" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_advanced.html:62 +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:6 +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:9 +msgid "List of Cached Values" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:12 +msgid "Prefix" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:13 +#: kallithea/templates/admin/repos/repo_edit_fields.html:7 +msgid "Key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_caches.html:14 +#: kallithea/templates/admin/user_groups/user_group_add.html:40 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17 +#: kallithea/templates/admin/user_groups/user_groups.html:41 +#: kallithea/templates/admin/users/user_add.html:69 +#: kallithea/templates/admin/users/user_edit_profile.html:74 +#: kallithea/templates/admin/users/users.html:42 +msgid "Active" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:6 +msgid "Label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:20 +#, python-format +msgid "Confirm to delete this field: %s" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:31 +msgid "New field key" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:38 +msgid "New field label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:40 +msgid "Enter short label" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:45 +msgid "New field description" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:47 +msgid "Enter description of a field" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_fields.html:61 +msgid "Extra fields are disabled." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_permissions.html:20 +msgid "Private Repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:4 +msgid "Fork of repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:7 +msgid "Remote repository URL" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:15 +msgid "Pull Changes from Remote Repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:17 +msgid "Confirm to pull changes from remote repository." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_remote.html:23 +msgid "This repository does not have a remote repository URL." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:10 +msgid "Permanent URL" +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 permanent URL guarantees " +"that this repository always will be accessible on that URL.\n" +" This is useful for CI systems, or any " +"other cases that you need to hardcode the URL into a 3rd party service." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:21 +msgid "Remote repository" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:24 +msgid "Repository URL" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:28 +msgid "" +"Optional: URL of a remote repository. If set, the repository can be " +"pulled from this URL." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:43 +msgid "Default revision for files page, downloads, whoosh and readme" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:49 +#: kallithea/templates/pullrequests/pullrequest_show.html:131 +msgid "Type name of user" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_settings.html:50 +msgid "Change owner of this repository." +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:5 +msgid "Processed commits" +msgstr "" + +#: kallithea/templates/admin/repos/repo_edit_statistics.html:6 +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:43 +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:4 +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 "Send test email to" +msgstr "" + +#: kallithea/templates/admin/settings/settings_email.html:12 +msgid "Send" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:4 +msgid "Site branding" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:7 +msgid "Set a custom title for your Kallithea Service." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:12 +msgid "HTTP authentication realm" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:19 +msgid "HTML/JavaScript/CSS customization block" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:22 +msgid "" +"HTML (possibly with JavaScript and/or CSS) that " +"will be added to the bottom of every page. This " +"can be used for web analytics systems, but also " +"to perform instance-specific customizations like " +"adding a project banner at the top of every page." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:32 +msgid "ReCaptcha public key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:35 +msgid "Public key for reCaptcha system." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:40 +msgid "ReCaptcha private key" +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:43 +msgid "" +"Private key for reCaptcha system. Setting this value will enable captcha " +"on registration." +msgstr "" + +#: kallithea/templates/admin/settings/settings_global.html:49 +#: kallithea/templates/admin/settings/settings_vcs.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:128 +msgid "Save Settings" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:3 +msgid "Built-in Mercurial Hooks (Read-Only)" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:17 +msgid "Custom Hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_hooks.html:18 +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:60 +msgid "Failed to remove hook" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:4 +msgid "Rescan options" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:9 +msgid "Delete records of missing repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:12 +msgid "" +"Check this option to remove all comments, pull requests and other records " +"related to repositories that no longer exist in 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:20 +msgid "Check this to reload data and clear cache keys for all repositories." +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:25 +msgid "Install Git hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:28 +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 "Overwrite existing Git hooks" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:35 +msgid "" +"If installing Git hooks, overwrite any existing hooks, even if they do " +"not seem to come from Kallithea. WARNING: This operation will destroy any " +"custom git hooks you may have deployed by hand!" +msgstr "" + +#: kallithea/templates/admin/settings/settings_mapping.html:41 +msgid "Rescan Repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:4 +msgid "Index build option" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:9 +msgid "Build from scratch" +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:12 +msgid "" +"This option completely reindexeses all of the repositories for proper " +"fulltext search capabilities." +msgstr "" + +#: kallithea/templates/admin/settings/settings_search.html:18 +msgid "Reindex" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:2 +msgid "Checking for updates..." +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:7 +msgid "Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:8 +msgid "Kallithea configuration file" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:9 +msgid "Python version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:10 +msgid "Platform" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:11 +msgid "Git version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:12 +msgid "Git path" +msgstr "" + +#: kallithea/templates/admin/settings/settings_system.html:22 +msgid "Python Packages" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:9 +msgid "Show repository size after push" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:15 +msgid "Update repository after push (hg update)" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:21 +msgid "Mercurial extensions" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:26 +msgid "Enable largefiles extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:32 +msgid "Enable hgsubversion extension" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:35 +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:47 +msgid "Location of repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:52 +msgid "" +"Click to unlock. You must restart Kallithea in order to make this setting " +"take effect." +msgstr "" + +#: kallithea/templates/admin/settings/settings_vcs.html:56 +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:4 +msgid "General" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:9 +msgid "Use repository extra fields" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:12 +msgid "Allows storing additional customized fields per repository." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:17 +msgid "Show Kallithea version" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:20 +msgid "" +"Shows or hides a version number of Kallithea displayed in the footer." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:25 +msgid "Show user Gravatars" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:29 +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:40 +msgid "HTTP Clone URL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:43 +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 construct clone-by-id,\n" +" {system_user} name " +"of the Kallithea system user,\n" +" {hostname} server " +"hostname\n" +" " +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:56 +msgid "SSH Clone URL" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:59 +msgid "" +"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}" +"@{hostname}/{repo}'." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:67 +msgid "Repository page size" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:70 +msgid "" +"Number of items displayed in the repository pages before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:75 +msgid "Admin page size" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:78 +msgid "" +"Number of items displayed in the admin pages grids before pagination is " +"shown." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:83 +msgid "Icons" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:88 +msgid "Show public repository icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:94 +msgid "Show private repository icon on repositories" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:97 +msgid "Show public/private icons next to repository names." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:102 +msgid "Meta Tagging" +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:107 +msgid "" +"Parses meta tags from the repository description field and turns them " +"into colored tags." +msgstr "" + +#: kallithea/templates/admin/settings/settings_visual.html:111 +msgid "Stylify recognised meta 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/admin/user_groups/user_groups.html:9 +#: kallithea/templates/base/base.html:59 +#: kallithea/templates/base/base.html:79 +msgid "User Groups" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:12 +#: kallithea/templates/admin/user_groups/user_groups.html:24 +msgid "Add User Group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_add.html:36 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:13 +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:33 +msgid "Show 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:6 +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:23 +#: kallithea/templates/admin/user_groups/user_groups.html:40 +msgid "Members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19 +#: kallithea/templates/data_table/_dt_elements.html:102 +#, python-format +msgid "Confirm to delete this user group: %s" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21 +msgid "Delete this user group" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_members.html:11 +msgid "No members yet" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:26 +msgid "Chosen group members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:39 +msgid "Available members" +msgstr "" + +#: kallithea/templates/admin/user_groups/user_groups.html:5 +msgid "User Groups Administration" +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:9 +#: kallithea/templates/base/base.html:58 +msgid "Users" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:12 +#: kallithea/templates/admin/users/users.html:23 +msgid "Add User" +msgstr "" + +#: kallithea/templates/admin/users/user_add.html:41 +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:30 +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:32 +msgid "Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:9 +#: kallithea/templates/admin/users/users.html:41 +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:90 +#, python-format +msgid "Confirm to delete this user: %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_advanced.html:23 +msgid "Delete this user" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_ips.html:7 +#, python-format +msgid "Inherited from %s" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:39 +msgid "Name in Source of Record" +msgstr "" + +#: kallithea/templates/admin/users/user_edit_profile.html:53 +msgid "New password confirmation" +msgstr "" + +#: kallithea/templates/admin/users/users.html:5 +msgid "Users Administration" +msgstr "" + +#: kallithea/templates/admin/users/users.html:44 +msgid "Auth Type" +msgstr "" + +#: kallithea/templates/base/base.html:16 +#, python-format +msgid "Server instance: %s" +msgstr "" + +#: kallithea/templates/base/base.html:28 +msgid "Support" +msgstr "" + +#: kallithea/templates/base/base.html:86 +#: kallithea/templates/base/base.html:417 +msgid "Mercurial repository" +msgstr "" + +#: kallithea/templates/base/base.html:89 +#: kallithea/templates/base/base.html:420 +msgid "Git repository" +msgstr "" + +#: kallithea/templates/base/base.html:115 +msgid "Create Fork" +msgstr "" + +#: kallithea/templates/base/base.html:127 +#: kallithea/templates/summary/summary.html:9 +msgid "Summary" +msgstr "" + +#: kallithea/templates/base/base.html:129 +#: kallithea/templates/base/base.html:131 +#: kallithea/templates/changelog/changelog.html:16 +msgid "Changelog" +msgstr "" + +#: kallithea/templates/base/base.html:133 +#: kallithea/templates/files/files.html:11 +msgid "Files" +msgstr "" + +#: kallithea/templates/base/base.html:135 +#, python-format +msgid "Show Pull Requests for %s" +msgstr "" + +#: kallithea/templates/base/base.html:135 +msgid "Pull Requests" +msgstr "" + +#: kallithea/templates/base/base.html:146 +#: kallithea/templates/base/base.html:148 +msgid "Options" +msgstr "" + +#: kallithea/templates/base/base.html:156 +#: kallithea/templates/forks/forks_data.html:18 +msgid "Compare Fork" +msgstr "" + +#: kallithea/templates/base/base.html:158 +msgid "Compare" +msgstr "" + +#: kallithea/templates/base/base.html:160 +#: kallithea/templates/base/base.html:315 +#: kallithea/templates/search/search.html:14 +#: kallithea/templates/search/search.html:67 +msgid "Search" +msgstr "" + +#: kallithea/templates/base/base.html:167 +msgid "Follow" +msgstr "" + +#: kallithea/templates/base/base.html:168 +msgid "Unfollow" +msgstr "" + +#: kallithea/templates/base/base.html:171 +#: kallithea/templates/forks/fork.html:9 +msgid "Fork" +msgstr "" + +#: kallithea/templates/base/base.html:172 +#: kallithea/templates/pullrequests/pullrequest.html:77 +msgid "Create Pull Request" +msgstr "" + +#: kallithea/templates/base/base.html:184 +msgid "Switch To" +msgstr "" + +#: kallithea/templates/base/base.html:196 +#: kallithea/templates/base/base.html:445 +msgid "No matches found" +msgstr "" + +#: kallithea/templates/base/base.html:289 +msgid "Show recent activity" +msgstr "" + +#: kallithea/templates/base/base.html:295 +#: kallithea/templates/base/base.html:296 +msgid "Public journal" +msgstr "" + +#: kallithea/templates/base/base.html:301 +msgid "Show public gists" +msgstr "" + +#: kallithea/templates/base/base.html:302 +msgid "Gists" +msgstr "" + +#: kallithea/templates/base/base.html:306 +msgid "All Public Gists" +msgstr "" + +#: kallithea/templates/base/base.html:308 +msgid "My Public Gists" +msgstr "" + +#: kallithea/templates/base/base.html:309 +msgid "My Private Gists" +msgstr "" + +#: kallithea/templates/base/base.html:314 +msgid "Search in repositories" +msgstr "" + +#: kallithea/templates/base/base.html:337 +#: kallithea/templates/base/base.html:338 +#: kallithea/templates/pullrequests/pullrequest_show_my.html:6 +#: kallithea/templates/pullrequests/pullrequest_show_my.html:10 +msgid "My Pull Requests" +msgstr "" + +#: kallithea/templates/base/base.html:353 +msgid "Not Logged In" +msgstr "" + +#: kallithea/templates/base/base.html:362 +msgid "Login to Your Account" +msgstr "" + +#: kallithea/templates/base/base.html:372 +msgid "Forgot password?" +msgstr "" + +#: kallithea/templates/base/base.html:376 +msgid "Don't have an account?" +msgstr "" + +#: kallithea/templates/base/base.html:393 +msgid "Log Out" +msgstr "" + +#: kallithea/templates/base/base.html:517 +msgid "Parent rev." +msgstr "" + +#: kallithea/templates/base/base.html:526 +msgid "Child rev." +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:11 +msgid "Create repositories" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:15 +msgid "Select this option to allow repository creation for this user" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:21 +msgid "Create user groups" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:25 +msgid "Select this option to allow user group creation for this user" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:31 +msgid "Fork repositories" +msgstr "" + +#: kallithea/templates/base/default_perms_box.html:35 +msgid "Select this option to allow repository forking for this user" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:13 +#: kallithea/templates/changelog/changelog.html:41 +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:55 +msgid "Permission" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:32 +#: kallithea/templates/base/perms_summary.html:57 +msgid "Edit Permission" +msgstr "" + +#: kallithea/templates/base/perms_summary.html:92 +msgid "No permission defined" +msgstr "" + +#: kallithea/templates/base/root.html:28 +msgid "Retry" +msgstr "" + +#: kallithea/templates/base/root.html:29 +#: kallithea/templates/changeset/changeset_file_comment.html:65 +msgid "Submitting ..." +msgstr "" + +#: kallithea/templates/base/root.html:30 +msgid "Unable to post" +msgstr "" + +#: kallithea/templates/base/root.html:31 +msgid "Add Another Comment" +msgstr "" + +#: kallithea/templates/base/root.html:32 +msgid "Stop following this repository" +msgstr "" + +#: kallithea/templates/base/root.html:33 +msgid "Start following this repository" +msgstr "" + +#: kallithea/templates/base/root.html:34 +msgid "Group" +msgstr "" + +#: kallithea/templates/base/root.html:35 +msgid "Loading ..." +msgstr "" + +#: kallithea/templates/base/root.html:36 +msgid "loading ..." +msgstr "" + +#: kallithea/templates/base/root.html:37 +msgid "Search truncated" +msgstr "" + +#: kallithea/templates/base/root.html:38 +msgid "No matching files" +msgstr "" + +#: kallithea/templates/base/root.html:39 +msgid "Open New Pull Request from {0}" +msgstr "" + +#: kallithea/templates/base/root.html:40 +msgid "Open New Pull Request for {0} → {1}" +msgstr "" + +#: kallithea/templates/base/root.html:41 +msgid "Show Selected Changesets {0} → {1}" +msgstr "" + +#: kallithea/templates/base/root.html:42 +msgid "Selection Link" +msgstr "" + +#: kallithea/templates/base/root.html:43 +#: kallithea/templates/changeset/diff_block.html:7 +msgid "Collapse Diff" +msgstr "" + +#: kallithea/templates/base/root.html:44 +msgid "Expand Diff" +msgstr "" + +#: kallithea/templates/base/root.html:45 +msgid "No revisions" +msgstr "" + +#: kallithea/templates/base/root.html:46 +msgid "Type name of user or member to grant permission" +msgstr "" + +#: kallithea/templates/base/root.html:47 +msgid "Failed to revoke permission" +msgstr "" + +#: kallithea/templates/base/root.html:48 +msgid "Confirm to revoke permission for {0}: {1} ?" +msgstr "" + +#: kallithea/templates/base/root.html:51 +#: kallithea/templates/compare/compare_diff.html:108 +msgid "Select changeset" +msgstr "" + +#: kallithea/templates/base/root.html:52 +msgid "Specify changeset" +msgstr "" + +#: kallithea/templates/base/root.html:53 +msgid "Click to sort ascending" +msgstr "" + +#: kallithea/templates/base/root.html:54 +msgid "Click to sort descending" +msgstr "" + +#: kallithea/templates/base/root.html:55 +msgid "No records found." +msgstr "" + +#: kallithea/templates/base/root.html:56 +msgid "Data error." +msgstr "" + +#: kallithea/templates/base/root.html:57 +msgid "Loading..." +msgstr "" + +#: kallithea/templates/changelog/changelog.html:8 +#, python-format +msgid "%s Changelog" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:23 +#, python-format +msgid "showing %d out of %d revision" +msgid_plural "showing %d out of %d revisions" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changelog/changelog.html:47 +msgid "Clear selection" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:54 +msgid "Go to tip of repository" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:59 +#: kallithea/templates/forks/forks_data.html:16 +#, python-format +msgid "Compare fork with %s" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:61 +#, python-format +msgid "Compare fork with parent repository (%s)" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:65 +#: kallithea/templates/files/files.html:29 +msgid "Branch filter:" +msgstr "" + +#: kallithea/templates/changelog/changelog.html:221 +#, fuzzy +#| msgid "There are no changesets yet" +msgid "There are no changes yet" +msgstr "Et sinn nach keng Ännerungen do" + +#: 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:38 +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 "" + +#: kallithea/templates/changelog/changelog_table.html:20 +msgid "First (oldest) changeset in this list" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:22 +msgid "Last (most recent) changeset in this list" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:24 +msgid "Position in this list of changesets" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:35 +#, python-format +msgid "" +"Changeset status: %s by %s\n" +"Click to open associated pull request %s" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:41 +#, python-format +msgid "Changeset status: %s by %s" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:60 +msgid "Expand commit message" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:76 +#, python-format +msgid "%s comments" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:80 +#: kallithea/templates/changeset/changeset.html:63 +#: kallithea/templates/changeset/changeset_range.html:84 +#, python-format +msgid "Bookmark %s" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:83 +#: kallithea/templates/changeset/changeset.html:67 +#: kallithea/templates/changeset/changeset_range.html:90 +#: kallithea/templates/pullrequests/pullrequest_show.html:165 +#, python-format +msgid "Tag %s" +msgstr "" + +#: kallithea/templates/changelog/changelog_table.html:102 +#: kallithea/templates/changeset/changeset.html:71 +#: kallithea/templates/changeset/changeset_range.html:94 +#, python-format +msgid "Branch %s" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:8 +#, python-format +msgid "%s Changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:34 +msgid "Changeset status" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:43 +#: kallithea/templates/changeset/diff_block.html:64 +#: kallithea/templates/files/diff_2way.html:51 +msgid "Raw diff" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:46 +msgid "Patch diff" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:49 +#: kallithea/templates/changeset/diff_block.html:66 +#: kallithea/templates/files/diff_2way.html:54 +msgid "Download diff" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:59 +#: kallithea/templates/changeset/changeset_range.html:80 +msgid "Merge" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:95 +msgid "Grafted from:" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:100 +msgid "Transplanted from:" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:106 +msgid "Replaced by:" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:120 +msgid "Preceded by:" +msgstr "" + +#: kallithea/templates/changeset/changeset.html:137 +#: kallithea/templates/compare/compare_diff.html:59 +#: kallithea/templates/pullrequests/pullrequest_show.html:290 +#, python-format +msgid "%s file changed" +msgid_plural "%s files changed" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/compare/compare_diff.html:61 +#: kallithea/templates/pullrequests/pullrequest_show.html:292 +#, python-format +msgid "%s file changed with %s insertions and %s deletions" +msgid_plural "%s files changed with %s insertions and %s deletions" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 +#: kallithea/templates/compare/compare_diff.html:81 +#: kallithea/templates/pullrequests/pullrequest_show.html:309 +#: kallithea/templates/pullrequests/pullrequest_show.html:333 +msgid "Show full diff anyway" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:20 +msgid "comment" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:21 +msgid "on pull request" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:22 +msgid "No title" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:24 +msgid "on this changeset" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:30 +msgid "Delete comment?" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:38 +#: kallithea/templates/changeset/changeset_file_comment.html:71 +msgid "Status change" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:87 +msgid "Comments are in plain text. Use @username to notify another user." +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:93 +msgid "Set changeset status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:95 +msgid "Vote for pull request status" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:101 +#: kallithea/templates/changeset/diff_block.html:46 +msgid "No change" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:114 +msgid "Finish pull request" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:117 +#, fuzzy +#| msgid "(closed)" +msgid "Close" +msgstr "(Zou)" + +#: kallithea/templates/changeset/changeset_file_comment.html:129 +msgid "Comment" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:137 +msgid "You need to be logged in to comment." +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:137 +msgid "Login now" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:141 +msgid "Hide" +msgstr "" + +#: kallithea/templates/changeset/changeset_file_comment.html:153 +#, python-format +msgid "%d comment" +msgid_plural "%d comments" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset_file_comment.html:154 +#, python-format +msgid "%d inline" +msgid_plural "%d inline" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset_file_comment.html:155 +#, python-format +msgid "%d general" +msgid_plural "%d general" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/changeset/changeset_range.html:5 +#, python-format +msgid "%s Changesets" +msgstr "" + +#: kallithea/templates/changeset/changeset_range.html:43 +#, python-format +msgid "Changeset status: %s" +msgstr "" + +#: kallithea/templates/changeset/changeset_range.html:50 +msgid "Files affected" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:30 +msgid "No file before" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:33 +msgid "File before" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:40 +msgid "Modified" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:42 +msgid "Deleted" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:44 +msgid "Renamed" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:48 +#, python-format +msgid "Unknown operation: %r" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:52 +msgid "No file after" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:55 +msgid "File after" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:60 +#: kallithea/templates/files/diff_2way.html:43 +msgid "Show full diff for this file" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:62 +#: kallithea/templates/files/diff_2way.html:47 +msgid "Show full side-by-side diff for this file" +msgstr "" + +#: kallithea/templates/changeset/diff_block.html:72 +msgid "Show inline comments" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:5 +#, fuzzy +#| msgid "There are no changesets yet" +msgid "No changesets" +msgstr "Et sinn nach keng Ännerungen do" + +#: kallithea/templates/compare/compare_cs.html:12 +msgid "Criss cross merge situation with multiple merge ancestors detected!" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:15 +msgid "" +"Please merge the target branch to your branch before creating a pull " +"request." +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:19 +msgid "Merge Ancestor" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:40 +msgid "Show merge diff" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:54 +msgid "is" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:55 +#, python-format +msgid "%s changesets" +msgstr "" + +#: kallithea/templates/compare/compare_cs.html:56 +msgid "behind" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:6 +#: kallithea/templates/compare/compare_diff.html:8 +#, python-format +msgid "%s Compare" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:13 +#: kallithea/templates/compare/compare_diff.html:41 +msgid "Compare Revisions" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:39 +msgid "Swap" +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:48 +msgid "Compare revisions, branches, bookmarks, or tags." +msgstr "" + +#: kallithea/templates/compare/compare_diff.html:53 +#: kallithea/templates/pullrequests/pullrequest_show.html:278 +#, python-format +msgid "Showing %s commit" +msgid_plural "Showing %s commits" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/compare/compare_diff.html:95 +msgid "Show full diff" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:23 +msgid "Public repository" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:29 +msgid "Repository creation in progress..." +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:42 +#, fuzzy +#| msgid "There are no changesets yet" +msgid "No changesets yet" +msgstr "Et sinn nach keng Ännerungen do" + +#: kallithea/templates/data_table/_dt_elements.html:48 +#: kallithea/templates/data_table/_dt_elements.html:50 +#, python-format +msgid "Subscribe to %s rss feed" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:56 +#: kallithea/templates/data_table/_dt_elements.html:58 +#, python-format +msgid "Subscribe to %s atom feed" +msgstr "" + +#: kallithea/templates/data_table/_dt_elements.html:76 +msgid "Creating" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:4 +#, python-format +msgid "Mention in Comment on Changeset \"%s\"" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:4 +#, python-format +msgid "Comment on Changeset \"%s\"" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:20 +msgid "Changeset on" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:23 +#: kallithea/templates/email_templates/pull_request.html:22 +#: kallithea/templates/email_templates/pull_request.html:28 +#: kallithea/templates/email_templates/pull_request_comment.html:30 +#: kallithea/templates/email_templates/pull_request_comment.html:36 +msgid "branch" +msgstr "" + +#: kallithea/templates/email_templates/changeset_comment.html:29 +#: kallithea/templates/email_templates/pull_request.html:15 +#: kallithea/templates/email_templates/pull_request_comment.html:23 +msgid "by" +msgstr "" + +#: kallithea/templates/email_templates/comment.html:27 +msgid "Status change:" +msgstr "" + +#: kallithea/templates/email_templates/comment.html:33 +msgid "The pull request has been closed." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:9 +#, python-format +msgid "Hello %s" +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:16 +msgid "We have received a request to reset the password for your account." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:25 +msgid "" +"This account is however managed outside this system and the password " +"cannot be changed here." +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:28 +msgid "To set a new password, click the following link" +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:33 +msgid "" +"Should you not be able to use the link above, please type the following " +"code into the password reset form" +msgstr "" + +#: kallithea/templates/email_templates/password_reset.html:44 +msgid "" +"If it weren't you who requested the password reset, just disregard this " +"message." +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:4 +#, python-format +msgid "Mention on Pull Request %s \"%s\" by %s" +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:4 +#, python-format +msgid "Added as Reviewer of Pull Request %s \"%s\" by %s" +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:12 +#: kallithea/templates/email_templates/pull_request_comment.html:20 +msgid "Pull request" +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:19 +#: kallithea/templates/email_templates/pull_request_comment.html:27 +msgid "from" +msgstr "" + +#: kallithea/templates/email_templates/pull_request.html:25 +#: kallithea/templates/email_templates/pull_request_comment.html:33 +msgid "to" +msgstr "" + +#: kallithea/templates/email_templates/pull_request_comment.html:4 +#, python-format +msgid "Mention in Comment on Pull Request %s \"%s\"" +msgstr "" + +#: kallithea/templates/email_templates/pull_request_comment.html:4 +#, python-format +msgid "Pull Request %s \"%s\" Closed" +msgstr "" + +#: kallithea/templates/email_templates/pull_request_comment.html:4 +#, python-format +msgid "Comment on Pull Request %s \"%s\"" +msgstr "" + +#: kallithea/templates/email_templates/registration.html:22 +msgid "Full Name" +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 "" + +#: kallithea/templates/files/files.html:4 +#: kallithea/templates/files/files.html:74 +#, python-format +msgid "%s Files" +msgstr "" + +#: kallithea/templates/files/files_add.html:4 +#, python-format +msgid "%s Files Add" +msgstr "" + +#: kallithea/templates/files/files_add.html:21 +#: kallithea/templates/files/files_ypjax.html:9 +#: kallithea/templates/summary/summary.html:199 +msgid "Add New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:39 +#: kallithea/templates/files/files_edit.html:39 +#: kallithea/templates/files/files_ypjax.html:3 +msgid "Location" +msgstr "" + +#: kallithea/templates/files/files_add.html:41 +msgid "Enter filename..." +msgstr "" + +#: kallithea/templates/files/files_add.html:43 +#: kallithea/templates/files/files_add.html:47 +msgid "or" +msgstr "" + +#: kallithea/templates/files/files_add.html:43 +msgid "Upload File" +msgstr "" + +#: kallithea/templates/files/files_add.html:47 +msgid "Create New File" +msgstr "" + +#: kallithea/templates/files/files_add.html:53 +msgid "New file type" +msgstr "" + +#: kallithea/templates/files/files_add.html:64 +#: kallithea/templates/files/files_delete.html:34 +#: kallithea/templates/files/files_edit.html:67 +msgid "Commit Message" +msgstr "" + +#: kallithea/templates/files/files_add.html:68 +#: kallithea/templates/files/files_delete.html:40 +#: kallithea/templates/files/files_edit.html:71 +msgid "Commit Changes" +msgstr "" + +#: kallithea/templates/files/files_browser.html:40 +msgid "Search File List" +msgstr "" + +#: kallithea/templates/files/files_browser.html:45 +msgid "Loading file list..." +msgstr "" + +#: kallithea/templates/files/files_browser.html:55 +#: kallithea/templates/summary/summary.html:153 +msgid "Size" +msgstr "" + +#: kallithea/templates/files/files_browser.html:56 +msgid "Last Revision" +msgstr "" + +#: kallithea/templates/files/files_browser.html:57 +msgid "Last Modified" +msgstr "" + +#: kallithea/templates/files/files_browser.html:58 +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:30 +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:51 +#: kallithea/templates/files/files_source.html:28 +msgid "Show Annotation" +msgstr "" + +#: kallithea/templates/files/files_edit.html:53 +#: kallithea/templates/files/files_source.html:31 +msgid "Download as Raw" +msgstr "" + +#: kallithea/templates/files/files_edit.html:56 +msgid "Source" +msgstr "" + +#: kallithea/templates/files/files_history_box.html:2 +#, python-format +msgid "%s author" +msgid_plural "%s authors" +msgstr[0] "" +msgstr[1] "" + +#: kallithea/templates/files/files_source.html:6 +msgid "Diff to Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:7 +msgid "Show at Revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:9 +msgid "Show Full History" +msgstr "" + +#: kallithea/templates/files/files_source.html:10 +msgid "Show Authors" +msgstr "" + +#: kallithea/templates/files/files_source.html:26 +msgid "Show Source" +msgstr "" + +#: kallithea/templates/files/files_source.html:34 +#, python-format +msgid "Edit on Branch: %s" +msgstr "" + +#: kallithea/templates/files/files_source.html:37 +msgid "Editing binary files not allowed" +msgstr "" + +#: kallithea/templates/files/files_source.html:40 +msgid "Editing files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:41 +msgid "Deleting files allowed only when on branch head revision" +msgstr "" + +#: kallithea/templates/files/files_source.html:58 +#, python-format +msgid "Binary file (%s)" +msgstr "" + +#: kallithea/templates/files/files_source.html:69 +msgid "File is too big to display." +msgstr "" + +#: kallithea/templates/files/files_source.html:71 +msgid "Show full annotation anyway." +msgstr "" + +#: kallithea/templates/files/files_source.html:73 +msgid "Show as raw." +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:5 +msgid "annotation" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:23 +msgid "Go Back" +msgstr "" + +#: kallithea/templates/files/files_ypjax.html:24 +msgid "No files at given path" +msgstr "" + +#: kallithea/templates/followers/followers.html:5 +#, python-format +msgid "%s Followers" +msgstr "" + +#: kallithea/templates/followers/followers.html:9 +#: kallithea/templates/summary/summary.html:138 +#: kallithea/templates/summary/summary.html:139 +msgid "Followers" +msgstr "" + +#: kallithea/templates/followers/followers_data.html:9 +msgid "Started following -" +msgstr "" + +#: kallithea/templates/forks/fork.html:5 +#, python-format +msgid "Fork repository %s" +msgstr "" + +#: kallithea/templates/forks/fork.html:25 +msgid "Fork name" +msgstr "" + +#: kallithea/templates/forks/fork.html:53 +msgid "Default revision for files page, downloads, whoosh, and readme." +msgstr "" + +#: kallithea/templates/forks/fork.html:58 +msgid "Private" +msgstr "" + +#: kallithea/templates/forks/fork.html:66 +msgid "Copy permissions" +msgstr "" + +#: kallithea/templates/forks/fork.html:69 +msgid "Copy permissions from forked repository" +msgstr "" + +#: kallithea/templates/forks/fork.html:75 +msgid "Update after clone" +msgstr "" + +#: kallithea/templates/forks/fork.html:78 +msgid "Checkout source after making a clone" +msgstr "" + +#: kallithea/templates/forks/fork.html:85 +msgid "Fork this Repository" +msgstr "" + +#: kallithea/templates/forks/forks.html:5 +#, python-format +msgid "%s Forks" +msgstr "" + +#: kallithea/templates/forks/forks.html:9 +#: kallithea/templates/summary/summary.html:144 +#: kallithea/templates/summary/summary.html:145 +msgid "Forks" +msgstr "" + +#: kallithea/templates/forks/forks_data.html:14 +msgid "Forked" +msgstr "" + +#: kallithea/templates/forks/forks_data.html:24 +#, fuzzy +#| msgid "There are no changesets yet" +msgid "There are no forks yet" +msgstr "Et sinn nach keng Ännerungen do" + +#: kallithea/templates/journal/journal.html:22 +msgid "ATOM journal feed" +msgstr "" + +#: kallithea/templates/journal/journal.html:23 +msgid "RSS journal feed" +msgstr "" + +#: kallithea/templates/journal/journal.html:34 +msgid "My Repositories" +msgstr "" + +#: kallithea/templates/journal/journal_data.html:42 +msgid "No entries yet" +msgstr "" + +#: kallithea/templates/journal/public_journal.html:10 +msgid "ATOM public journal feed" +msgstr "" + +#: kallithea/templates/journal/public_journal.html:11 +msgid "RSS public journal feed" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:4 +#: kallithea/templates/pullrequests/pullrequest.html:8 +msgid "New Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:26 +#: kallithea/templates/pullrequests/pullrequest_data.html:15 +#: kallithea/templates/pullrequests/pullrequest_show.html:29 +#: kallithea/templates/pullrequests/pullrequest_show.html:52 +msgid "Title" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:28 +msgid "Summarize the changes - or leave empty" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:35 +#: kallithea/templates/pullrequests/pullrequest_show.html:61 +msgid "Write a short description on this pull request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:40 +msgid "Changeset flow" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:46 +msgid "Origin repository" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:52 +#: kallithea/templates/pullrequests/pullrequest.html:68 +msgid "Revision" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest.html:62 +msgid "Destination repository" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:6 +msgid "No entries" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:14 +msgid "Vote" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:17 +msgid "Age" +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:28 +#, python-format +msgid "You voted: %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:30 +msgid "You didn't vote" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:35 +msgid "(no title)" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:37 +#: kallithea/templates/pullrequests/pullrequest_show.html:31 +#: kallithea/templates/pullrequests/pullrequest_show.html:73 +#, fuzzy +#| msgid "(closed)" +msgid "Closed" +msgstr "(Zou)" + +#: kallithea/templates/pullrequests/pullrequest_data.html:67 +msgid "Delete Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:68 +msgid "Confirm to delete this pull request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_data.html:70 +#, python-format +msgid "Confirm again to delete this pull request with %s comments" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:6 +#, python-format +msgid "%s Pull Request %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:10 +#, python-format +msgid "Pull request %s from %s#%s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:54 +msgid "Summarize the changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:67 +msgid "Voting Result" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:70 +#: kallithea/templates/pullrequests/pullrequest_show.html:71 +msgid "Pull request status calculated from votes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:81 +msgid "Origin" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:86 +msgid "on" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:92 +msgid "Target" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:95 +msgid "" +"This is just a range of changesets and doesn't have a target or a real " +"merge ancestor." +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:103 +msgid "Pull changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:136 +msgid "Next iteration" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:153 +msgid "Current revision - no change" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:177 +msgid "" +"Pull request iterations do not change content once created. Select a " +"revision to create a new iteration." +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:187 +msgid "Save Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:188 +msgid "Create New Iteration with Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:189 +msgid "Cancel Changes" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:197 +msgid "Reviewers" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:223 +msgid "Remove reviewer" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:234 +msgid "Type name of reviewer to add" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:240 +msgid "Potential Reviewers" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:243 +msgid "Click to add the repository owner as reviewer:" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:268 +msgid "Pull Request Content" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show.html:283 +msgid "Common ancestor" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:6 +#, python-format +msgid "%s Pull Requests" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:11 +#, python-format +msgid "Pull Requests from '%s'" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:13 +#, python-format +msgid "Pull Requests to '%s'" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:31 +msgid "Open New Pull Request" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:34 +#, python-format +msgid "Show Pull Requests to %s" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:36 +#, python-format +msgid "Show Pull Requests from '%s'" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:44 +#: kallithea/templates/pullrequests/pullrequest_show_my.html:28 +msgid "Hide closed pull requests (only show open pull requests)" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_all.html:46 +#: kallithea/templates/pullrequests/pullrequest_show_my.html:30 +msgid "Show closed pull requests (in addition to open pull requests)" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_my.html:34 +msgid "Pull Requests Created by Me" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_my.html:37 +msgid "Pull Requests Needing My Review" +msgstr "" + +#: kallithea/templates/pullrequests/pullrequest_show_my.html:40 +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:47 +msgid "Search term" +msgstr "" + +#: kallithea/templates/search/search.html:54 +msgid "Search in" +msgstr "" + +#: kallithea/templates/search/search.html:56 +msgid "File contents" +msgstr "" + +#: kallithea/templates/search/search.html:57 +msgid "Commit messages" +msgstr "" + +#: kallithea/templates/search/search.html:58 +msgid "File names" +msgstr "" + +#: kallithea/templates/search/search_commit.html:30 +#: kallithea/templates/search/search_content.html:18 +#: 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:27 +#, python-format +msgid "%s ATOM feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:17 +#: kallithea/templates/summary/summary.html:28 +#, python-format +msgid "%s RSS feed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:35 +#: kallithea/templates/summary/summary.html:99 +#: kallithea/templates/summary/summary.html:113 +msgid "Enable" +msgstr "" + +#: kallithea/templates/summary/statistics.html:38 +msgid "Stats gathered: " +msgstr "" + +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 +msgid "files" +msgstr "" + +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 +msgid "Show more" +msgstr "" + +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:405 +msgid "files changed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:408 +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:410 +msgid "file changed" +msgstr "" + +#: kallithea/templates/summary/statistics.html:411 +msgid "file removed" +msgstr "" + +#: kallithea/templates/summary/summary.html:5 +#, python-format +msgid "%s Summary" +msgstr "" + +#: kallithea/templates/summary/summary.html:13 +msgid "Fork of" +msgstr "" + +#: kallithea/templates/summary/summary.html:18 +msgid "Clone from" +msgstr "" + +#: kallithea/templates/summary/summary.html:54 +msgid "Clone URL" +msgstr "" + +#: kallithea/templates/summary/summary.html:63 +msgid "Use ID" +msgstr "" + +#: kallithea/templates/summary/summary.html:65 +#: kallithea/templates/summary/summary.html:73 +msgid "Use SSH" +msgstr "" + +#: kallithea/templates/summary/summary.html:71 +msgid "Use Name" +msgstr "" + +#: kallithea/templates/summary/summary.html:80 +msgid "Use HTTP" +msgstr "" + +#: kallithea/templates/summary/summary.html:92 +msgid "Trending files" +msgstr "" + +#: kallithea/templates/summary/summary.html:106 +msgid "Download" +msgstr "" + +#: kallithea/templates/summary/summary.html:109 +#, fuzzy +#| msgid "There are no changesets yet" +msgid "There are no downloads yet" +msgstr "Et sinn nach keng Ännerungen do" + +#: kallithea/templates/summary/summary.html:111 +msgid "Downloads are disabled for this repository" +msgstr "" + +#: kallithea/templates/summary/summary.html:117 +msgid "Download as zip" +msgstr "" + +#: kallithea/templates/summary/summary.html:121 +msgid "Check this to download archive with subrepos" +msgstr "" + +#: kallithea/templates/summary/summary.html:123 +msgid "With subrepos" +msgstr "" + +#: kallithea/templates/summary/summary.html:161 +#: kallithea/templates/summary/summary.html:163 +msgid "Feed" +msgstr "" + +#: kallithea/templates/summary/summary.html:183 +msgid "Latest Changes" +msgstr "" + +#: kallithea/templates/summary/summary.html:185 +msgid "Quick Start" +msgstr "" + +#: kallithea/templates/summary/summary.html:196 +msgid "Add or upload files directly via Kallithea" +msgstr "" + +#: kallithea/templates/summary/summary.html:204 +msgid "Push new repository" +msgstr "" + +#: kallithea/templates/summary/summary.html:212 +msgid "Existing repository?" +msgstr "" + +#: kallithea/templates/summary/summary.html:230 +#, python-format +msgid "Readme file from revision %s:%s" +msgstr "" + +#: kallithea/templates/summary/summary.html:315 +#, python-format +msgid "Download %s as %s" +msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/nb_NO/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/nb_NO/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/nb_NO/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3.99\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-04-30 22:25+0000\n" "Last-Translator: Allan Nordhøy \n" "Language-Team: Norwegian Bokmål %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "Forgreningsnavn %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "Flettingsforespørsel %s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 #, fuzzy msgid "[deleted] repository" msgstr "[slettet] pakkebrønn" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 #, fuzzy msgid "[created] repository" msgstr "[opprettet] pakkebrønn" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[opprettet] pakkebrønn som forgrening" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 #, fuzzy msgid "[forked] repository" msgstr "[forgrenet] pakkebrønn" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 #, fuzzy msgid "[updated] repository" msgstr "[oppdaterte] pakkebrønn" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 #, fuzzy msgid "[downloaded] archive from repository" msgstr "[lastet ned] arkiv fra pakkebrønn" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 #, fuzzy msgid "[delete] repository" msgstr "[slett] pakkebrønn" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "[opprettet] bruker" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "[oppdaterte] bruker" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "[opprettet] brukergruppe" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "[oppdaterte] brukergruppe" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 #, fuzzy msgid "[commented] on revision in repository" msgstr "[kommenterte] en revisjon i pakkebrønn" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "[kommenterte] flettingsforespørsel for" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "[lukket] flettingsforespørsel for" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[dyttet] til" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 #, fuzzy msgid "[committed via Kallithea] into repository" msgstr "[innsendt via Kallithea] inn i pakkebrønn" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Ingen filer" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "ny fil" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1273,96 +1273,98 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d år" msgstr[1] "%d år" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d måned" msgstr[1] "%d måneder" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dager" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d time" msgstr[1] "%d timer" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minutt" msgstr[1] "%d minutter" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "om %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "for %s siden" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "om %s og %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s og %s siden" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "akkurat nå" @@ -1371,134 +1373,134 @@ msgid "on line %s" msgstr "på linje %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "toppnivå" -#: kallithea/model/db.py:1637 +#: kallithea/model/db.py:1634 msgid "Kallithea Administrator" msgstr "Kallithea-administrator" -#: kallithea/model/db.py:1639 +#: kallithea/model/db.py:1636 #, fuzzy msgid "Default user has no access to new repositories" msgstr "Forvalgt bruker har ingen tilgang til nye pakkebrønner" -#: kallithea/model/db.py:1640 +#: kallithea/model/db.py:1637 msgid "Default user has read access to new repositories" msgstr "" +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1639 +msgid "Default user has admin access to new repositories" +msgstr "" + #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 +msgid "Not reviewed" +msgstr "" + +#: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 msgid "Not approved" msgstr "Ikke godkjent" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "Godkjent" @@ -1524,145 +1526,145 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "Lukker" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" -msgstr "" - -#: kallithea/model/user.py:186 +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2359,7 +2361,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3410,7 +3412,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "Lagre innstillinger" @@ -3652,53 +3654,53 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4340,23 +4342,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4365,7 +4367,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4374,8 +4376,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5339,45 +5341,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/nl_BE/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/nl_BE/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/nl_BE/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-10-05 19:28+0000\n" "Last-Translator: Thomas De Schampheleire \n" "Language-Team: Flemish %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1242,96 +1242,98 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1340,133 +1342,133 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1492,145 +1494,146 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" +#: kallithea/model/ssh_key.py:88 +#, fuzzy, python-format +#| msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "SSH key %r werd niet gevonden" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2319,7 +2322,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3362,7 +3365,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3602,53 +3605,53 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "Repository paginagrootte" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4276,23 +4279,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4301,7 +4304,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4310,8 +4313,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5271,45 +5274,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/pl/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/pl/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/pl/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2020-01-27 15:21+0000\n" "Last-Translator: robertus \n" "Language-Team: Polish =2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2;\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n" +"%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 3.11-dev\n" #: kallithea/controllers/changelog.py:67 -#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602 +#: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:602 msgid "There are no changesets yet" msgstr "Brak zestawienia zmian" #: kallithea/controllers/admin/permissions.py:64 #: kallithea/controllers/admin/permissions.py:68 #: kallithea/controllers/admin/permissions.py:72 -#: kallithea/controllers/changelog.py:137 +#: kallithea/controllers/changelog.py:136 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7 @@ -34,38 +34,38 @@ msgid "None" msgstr "Brak" -#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189 +#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:189 msgid "(closed)" msgstr "(zamknięty)" -#: kallithea/controllers/changeset.py:81 +#: kallithea/controllers/changeset.py:82 msgid "Show whitespace" msgstr "pokazuj spacje" -#: kallithea/controllers/changeset.py:88 -#: kallithea/controllers/changeset.py:95 +#: kallithea/controllers/changeset.py:89 +#: kallithea/controllers/changeset.py:96 #: kallithea/templates/files/diff_2way.html:55 msgid "Ignore whitespace" msgstr "Ignoruj pokazywanie spacji" -#: kallithea/controllers/changeset.py:161 +#: kallithea/controllers/changeset.py:162 #, python-format msgid "Increase diff context to %(num)s lines" msgstr "" -#: kallithea/controllers/changeset.py:201 +#: kallithea/controllers/changeset.py:202 #, fuzzy msgid "No permission to change status" msgstr "Brak uprawnień do zmiany statusu" -#: kallithea/controllers/changeset.py:212 +#: kallithea/controllers/changeset.py:213 #, python-format msgid "Successfully deleted pull request %s" msgstr "" "Prośba o skasowanie połączenia gałęzi %s została wykonana prawidłowo" -#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89 -#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700 +#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89 +#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697 msgid "Such revision does not exist for this repository" msgstr "" @@ -78,50 +78,50 @@ msgid "Cannot compare repositories of different types" msgstr "" -#: kallithea/controllers/compare.py:246 +#: kallithea/controllers/compare.py:247 msgid "Cannot show empty diff" msgstr "" -#: kallithea/controllers/compare.py:248 +#: kallithea/controllers/compare.py:249 msgid "No ancestor found for merge diff" msgstr "" -#: kallithea/controllers/compare.py:252 +#: kallithea/controllers/compare.py:253 msgid "Multiple merge ancestors found for merge compare" msgstr "" -#: kallithea/controllers/compare.py:268 +#: kallithea/controllers/compare.py:269 msgid "Cannot compare repositories without using common ancestor" msgstr "" +#: kallithea/controllers/error.py:70 +msgid "No response" +msgstr "Brak odpowiedzi" + #: kallithea/controllers/error.py:71 -msgid "No response" -msgstr "Brak odpowiedzi" - -#: kallithea/controllers/error.py:72 msgid "Unknown error" msgstr "Nieznany błąd" -#: kallithea/controllers/error.py:85 +#: kallithea/controllers/error.py:84 msgid "" "The request could not be understood by the server due to malformed syntax." msgstr "" "Żądanie nie może być rozumiane przez serwer z powodu zniekształconej " "składni." -#: kallithea/controllers/error.py:88 +#: kallithea/controllers/error.py:87 msgid "Unauthorized access to resource" msgstr "Nieautoryzowany dostęp do zasobów" -#: kallithea/controllers/error.py:90 +#: kallithea/controllers/error.py:89 msgid "You don't have permission to view this page" msgstr "Nie masz uprawnień do przeglądania tej strony" -#: kallithea/controllers/error.py:92 +#: kallithea/controllers/error.py:91 msgid "The resource could not be found" msgstr "Zasób nie został znaleziony" -#: kallithea/controllers/error.py:94 +#: kallithea/controllers/error.py:93 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." @@ -129,14 +129,14 @@ "Serwer napotkał niespodziewany warunek, który uniemożliwia spełnienie " "żądania." -#: kallithea/controllers/feed.py:63 +#: kallithea/controllers/feed.py:59 #, python-format msgid "%s committed on %s" msgstr "%s zakomitowal w %s" -#: kallithea/controllers/feed.py:88 -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/controllers/feed.py:84 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/compare/compare_diff.html:95 #: kallithea/templates/pullrequests/pullrequest_show.html:309 @@ -144,12 +144,12 @@ msgid "Changeset was too big and was cut off..." msgstr "Lista zmian była zbyt duża i została ucięta..." -#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140 +#: kallithea/controllers/feed.py:107 #, python-format msgid "%s %s feed" msgstr "%s %s zasilać" -#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142 +#: kallithea/controllers/feed.py:109 #, python-format msgid "Changes on %s repository" msgstr "Zmiany w %s repozytorium" @@ -167,93 +167,93 @@ msgid "%s at %s" msgstr "w %s i %s" -#: kallithea/controllers/files.py:296 +#: kallithea/controllers/files.py:295 #, fuzzy msgid "You can only delete files with revision being a valid branch" msgstr "Można tylko usuwać pliki po sprawdzeniu obecnej gałęzi" -#: kallithea/controllers/files.py:307 +#: kallithea/controllers/files.py:306 #, python-format msgid "Deleted file %s via Kallithea" msgstr "" -#: kallithea/controllers/files.py:331 +#: kallithea/controllers/files.py:330 #, python-format msgid "Successfully deleted file %s" msgstr "" -#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394 -#: kallithea/controllers/files.py:469 +#: kallithea/controllers/files.py:334 kallithea/controllers/files.py:392 +#: kallithea/controllers/files.py:467 msgid "Error occurred during commit" msgstr "Wystąpił błąd w trakcie zatwierdzania" -#: kallithea/controllers/files.py:350 +#: kallithea/controllers/files.py:349 #, fuzzy msgid "You can only edit files with revision being a valid branch" msgstr "Można tylko edytować pliki z rewizji obecnej gałęzi" -#: kallithea/controllers/files.py:364 +#: kallithea/controllers/files.py:363 #, python-format msgid "Edited file %s via Kallithea" msgstr "Edytowanie %s w Kallithea" -#: kallithea/controllers/files.py:380 +#: kallithea/controllers/files.py:378 msgid "No changes" msgstr "Bez zmian" -#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458 +#: kallithea/controllers/files.py:388 kallithea/controllers/files.py:456 #, python-format msgid "Successfully committed to %s" msgstr "Committ wykonany do %s" -#: kallithea/controllers/files.py:409 +#: kallithea/controllers/files.py:407 msgid "Added file via Kallithea" msgstr "Dodano %s poprzez Kallithea" -#: kallithea/controllers/files.py:430 +#: kallithea/controllers/files.py:428 msgid "No content" msgstr "Brak treści" -#: kallithea/controllers/files.py:434 +#: kallithea/controllers/files.py:432 msgid "No filename" msgstr "Brak nazwy pliku" -#: kallithea/controllers/files.py:461 +#: kallithea/controllers/files.py:459 msgid "Location must be relative path and must not contain .. in path" msgstr "" "Lokalizacja musi być ścieżką względną i nie może zawierać .. ścieżki" -#: kallithea/controllers/files.py:493 +#: kallithea/controllers/files.py:491 msgid "Downloads disabled" msgstr "Pobieranie wyłączone" -#: kallithea/controllers/files.py:504 +#: kallithea/controllers/files.py:502 #, python-format msgid "Unknown revision %s" msgstr "Nieznana wersja %s" -#: kallithea/controllers/files.py:506 +#: kallithea/controllers/files.py:504 msgid "Empty repository" msgstr "Puste repozytorium" -#: kallithea/controllers/files.py:508 +#: kallithea/controllers/files.py:506 msgid "Unknown archive type" msgstr "Nieznany typ archiwum" -#: kallithea/controllers/files.py:729 +#: kallithea/controllers/files.py:726 #: kallithea/templates/changeset/changeset_range.html:9 #: kallithea/templates/email_templates/pull_request.html:64 #: kallithea/templates/pullrequests/pullrequest.html:84 msgid "Changesets" msgstr "Różnice" -#: kallithea/controllers/files.py:730 -#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676 +#: kallithea/controllers/files.py:727 +#: kallithea/controllers/pullrequests.py:174 kallithea/model/scm.py:663 msgid "Branches" msgstr "Gałęzie" -#: kallithea/controllers/files.py:731 -#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687 +#: kallithea/controllers/files.py:728 +#: kallithea/controllers/pullrequests.py:175 kallithea/model/scm.py:674 msgid "Tags" msgstr "Etykiety" @@ -262,11 +262,11 @@ msgid "An error occurred during repository forking %s" msgstr "Wystąpił błąd podczas rozgałęzienia %s repozytorium" -#: kallithea/controllers/home.py:79 +#: kallithea/controllers/home.py:77 msgid "Groups" msgstr "Grupy" -#: kallithea/controllers/home.py:89 +#: kallithea/controllers/home.py:87 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90 #: kallithea/templates/admin/repos/repo_add.html:12 #: kallithea/templates/admin/repos/repo_add.html:16 @@ -278,196 +278,196 @@ msgid "Repositories" msgstr "Repozytoria" -#: kallithea/controllers/home.py:122 +#: kallithea/controllers/home.py:119 #: kallithea/templates/files/files_add.html:32 #: kallithea/templates/files/files_delete.html:23 #: kallithea/templates/files/files_edit.html:32 msgid "Branch" msgstr "gałąź" -#: kallithea/controllers/home.py:128 +#: kallithea/controllers/home.py:125 msgid "Closed Branches" msgstr "Zamknięte Gałęzie" -#: kallithea/controllers/home.py:134 +#: kallithea/controllers/home.py:131 msgid "Tag" msgstr "Tag" -#: kallithea/controllers/home.py:140 +#: kallithea/controllers/home.py:137 msgid "Bookmark" msgstr "Zakładka" -#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154 +#: kallithea/controllers/journal.py:146 kallithea/controllers/journal.py:157 #: kallithea/templates/journal/public_journal.html:4 #: kallithea/templates/journal/public_journal.html:18 msgid "Public Journal" msgstr "Dziennik Publiczny" -#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158 +#: kallithea/controllers/journal.py:150 kallithea/controllers/journal.py:161 #: kallithea/templates/base/base.html:290 #: kallithea/templates/journal/journal.html:5 #: kallithea/templates/journal/journal.html:13 msgid "Journal" msgstr "Dziennik" -#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185 +#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184 msgid "Bad captcha" msgstr "" -#: kallithea/controllers/login.py:146 +#: kallithea/controllers/login.py:145 #, python-format msgid "You have successfully registered with %s" msgstr "Udało Ci się zarejestrować w %s" -#: kallithea/controllers/login.py:190 +#: kallithea/controllers/login.py:189 msgid "A password reset confirmation code has been sent" msgstr "Twój link zresetowania hasła został wysłany" -#: kallithea/controllers/login.py:239 +#: kallithea/controllers/login.py:236 msgid "Invalid password reset token" msgstr "Nieprawidłowy token resetowania hasła" #: kallithea/controllers/admin/my_account.py:157 -#: kallithea/controllers/login.py:244 +#: kallithea/controllers/login.py:241 msgid "Successfully updated password" msgstr "Pomyślnie zaktualizowano hasło" -#: kallithea/controllers/pullrequests.py:68 +#: kallithea/controllers/pullrequests.py:67 #, python-format msgid "Invalid reviewer \"%s\" specified" msgstr "" -#: kallithea/controllers/pullrequests.py:131 +#: kallithea/controllers/pullrequests.py:123 #, python-format msgid "%s (closed)" msgstr "%s (zamknięty)" -#: kallithea/controllers/pullrequests.py:158 +#: kallithea/controllers/pullrequests.py:150 #: kallithea/templates/changeset/changeset.html:12 msgid "Changeset" msgstr "Grupy zmian" -#: kallithea/controllers/pullrequests.py:179 +#: kallithea/controllers/pullrequests.py:171 msgid "Special" msgstr "Specjalne" -#: kallithea/controllers/pullrequests.py:180 +#: kallithea/controllers/pullrequests.py:172 msgid "Peer branches" msgstr "gałęzie" -#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682 +#: kallithea/controllers/pullrequests.py:173 kallithea/model/scm.py:669 msgid "Bookmarks" msgstr "Zakładki" -#: kallithea/controllers/pullrequests.py:318 +#: kallithea/controllers/pullrequests.py:315 #, python-format msgid "Error creating pull request: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:345 -#: kallithea/controllers/pullrequests.py:368 +#: kallithea/controllers/pullrequests.py:342 +#: kallithea/controllers/pullrequests.py:365 msgid "Error occurred while creating pull request" msgstr "Wystąpił błąd podczas prośby o połączenie gałęzi" -#: kallithea/controllers/pullrequests.py:350 +#: kallithea/controllers/pullrequests.py:347 msgid "Successfully opened new pull request" msgstr "Prośba o wykonanie połączenia gałęzi została wykonana prawidłowo" -#: kallithea/controllers/pullrequests.py:373 +#: kallithea/controllers/pullrequests.py:370 #, fuzzy #| msgid "Pull request update created" msgid "New pull request iteration created" msgstr "Recenzje wniosków połączenia gałęzi" -#: kallithea/controllers/pullrequests.py:401 +#: kallithea/controllers/pullrequests.py:398 #, python-format msgid "Meanwhile, the following reviewers have been added: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:405 +#: kallithea/controllers/pullrequests.py:402 #, python-format msgid "Meanwhile, the following reviewers have been removed: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:421 -#: kallithea/model/pull_request.py:232 +#: kallithea/controllers/pullrequests.py:418 +#: kallithea/model/pull_request.py:230 msgid "No description" msgstr "Brak opisu" -#: kallithea/controllers/pullrequests.py:430 +#: kallithea/controllers/pullrequests.py:427 msgid "Pull request updated" msgstr "Połączone gałęzie zaktualizowane" -#: kallithea/controllers/pullrequests.py:443 +#: kallithea/controllers/pullrequests.py:440 msgid "Successfully deleted pull request" msgstr "Prośba o skasowanie połączenia gałęzi została wykonana prawidłowo" -#: kallithea/controllers/pullrequests.py:479 +#: kallithea/controllers/pullrequests.py:476 #, python-format msgid "Revision %s not found in %s" msgstr "" -#: kallithea/controllers/pullrequests.py:506 +#: kallithea/controllers/pullrequests.py:504 #, python-format msgid "Error: changesets not found when displaying pull request from %s." msgstr "" +#: kallithea/controllers/pullrequests.py:518 +#, python-format +msgid "This pull request has already been merged to %s." +msgstr "" + #: kallithea/controllers/pullrequests.py:520 -#, python-format -msgid "This pull request has already been merged to %s." -msgstr "" - -#: kallithea/controllers/pullrequests.py:522 msgid "This pull request has been closed and can not be updated." msgstr "" -#: kallithea/controllers/pullrequests.py:546 +#: kallithea/controllers/pullrequests.py:539 #, python-format msgid "The following additional changes are available on %s:" msgstr "" -#: kallithea/controllers/pullrequests.py:548 -#: kallithea/controllers/pullrequests.py:552 +#: kallithea/controllers/pullrequests.py:541 +#: kallithea/controllers/pullrequests.py:545 msgid "No additional changesets found for iterating on this pull request." msgstr "" +#: kallithea/controllers/pullrequests.py:553 +#, python-format +msgid "Note: Branch %s has another head: %s." +msgstr "" + #: kallithea/controllers/pullrequests.py:560 -#, python-format -msgid "Note: Branch %s has another head: %s." -msgstr "" - -#: kallithea/controllers/pullrequests.py:567 msgid "Git pull requests don't support iterating yet." msgstr "" -#: kallithea/controllers/pullrequests.py:569 +#: kallithea/controllers/pullrequests.py:562 #, python-format msgid "" "Error: some changesets not found when displaying pull request from %s." msgstr "" -#: kallithea/controllers/pullrequests.py:593 +#: kallithea/controllers/pullrequests.py:586 msgid "The diff can't be shown - the PR revisions could not be found." msgstr "" -#: kallithea/controllers/search.py:136 +#: kallithea/controllers/search.py:132 msgid "Invalid search query. Try quoting it." msgstr "Nieprawidłowe zapytanie. Spróbuj zacytować je." -#: kallithea/controllers/search.py:140 +#: kallithea/controllers/search.py:136 msgid "The server has no search index." msgstr "" -#: kallithea/controllers/search.py:143 +#: kallithea/controllers/search.py:139 msgid "An error occurred during search operation." msgstr "Wystąpił błąd podczas operacji wyszukiwania." -#: kallithea/controllers/summary.py:168 -#: kallithea/templates/summary/summary.html:412 +#: kallithea/controllers/summary.py:169 +#: kallithea/templates/summary/summary.html:410 msgid "No data ready yet" msgstr "Żadne dane nie zostały załadowane" -#: kallithea/controllers/summary.py:171 +#: kallithea/controllers/summary.py:172 #: kallithea/templates/summary/summary.html:97 msgid "Statistics are disabled for this repository" msgstr "Statystyki są wyłączone dla tego repozytorium" @@ -480,80 +480,80 @@ msgid "error occurred during update of auth settings" msgstr "wystąpił błąd podczas uaktualniania ustawień autentykacji" -#: kallithea/controllers/admin/defaults.py:75 +#: kallithea/controllers/admin/defaults.py:74 msgid "Default settings updated successfully" msgstr "Domyślne ustawienia zostały pomyślnie zaktualizowane" -#: kallithea/controllers/admin/defaults.py:90 +#: kallithea/controllers/admin/defaults.py:89 msgid "Error occurred during update of defaults" msgstr "wystąpił błąd podczas aktualizacji wartości domyślnych" #: kallithea/controllers/admin/gists.py:59 #: kallithea/controllers/admin/my_account.py:232 -#: kallithea/controllers/admin/users.py:248 +#: kallithea/controllers/admin/users.py:246 msgid "Forever" msgstr "na zawsze" #: kallithea/controllers/admin/gists.py:60 #: kallithea/controllers/admin/my_account.py:233 -#: kallithea/controllers/admin/users.py:249 +#: kallithea/controllers/admin/users.py:247 msgid "5 minutes" msgstr "5 minut" #: kallithea/controllers/admin/gists.py:61 #: kallithea/controllers/admin/my_account.py:234 -#: kallithea/controllers/admin/users.py:250 +#: kallithea/controllers/admin/users.py:248 msgid "1 hour" msgstr "1 godzina" #: kallithea/controllers/admin/gists.py:62 #: kallithea/controllers/admin/my_account.py:235 -#: kallithea/controllers/admin/users.py:251 +#: kallithea/controllers/admin/users.py:249 msgid "1 day" msgstr "1 dzień" #: kallithea/controllers/admin/gists.py:63 #: kallithea/controllers/admin/my_account.py:236 -#: kallithea/controllers/admin/users.py:252 +#: kallithea/controllers/admin/users.py:250 msgid "1 month" msgstr "1 miesiąc" #: kallithea/controllers/admin/gists.py:67 #: kallithea/controllers/admin/my_account.py:238 -#: kallithea/controllers/admin/users.py:254 +#: kallithea/controllers/admin/users.py:252 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65 #: kallithea/templates/admin/users/user_edit_api_keys.html:65 msgid "Lifetime" msgstr "Czas życia" -#: kallithea/controllers/admin/gists.py:142 +#: kallithea/controllers/admin/gists.py:148 msgid "Error occurred during gist creation" msgstr "Wystąpił błąd podczas tworzenia gist" -#: kallithea/controllers/admin/gists.py:158 +#: kallithea/controllers/admin/gists.py:164 #, python-format msgid "Deleted gist %s" msgstr "Usuń gist %s" -#: kallithea/controllers/admin/gists.py:198 +#: kallithea/controllers/admin/gists.py:207 msgid "Unmodified" msgstr "Niemodyfikowany" -#: kallithea/controllers/admin/gists.py:228 +#: kallithea/controllers/admin/gists.py:237 msgid "Successfully updated gist content" msgstr "" -#: kallithea/controllers/admin/gists.py:233 +#: kallithea/controllers/admin/gists.py:242 msgid "Successfully updated gist data" msgstr "" -#: kallithea/controllers/admin/gists.py:236 +#: kallithea/controllers/admin/gists.py:245 #, python-format msgid "Error occurred during update of gist %s" msgstr "" -#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211 -#: kallithea/model/user.py:232 +#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209 +#: kallithea/model/user.py:230 msgid "You can't edit this user since it's crucial for entire application" msgstr "" "Nie możesz edytować tego użytkownika ponieważ jest kluczowy dla całej " @@ -564,7 +564,7 @@ msgstr "Twoje konto zostało pomyślnie zaktualizowane" #: kallithea/controllers/admin/my_account.py:134 -#: kallithea/controllers/admin/users.py:181 +#: kallithea/controllers/admin/users.py:179 #, python-format msgid "Error occurred during update of user %s" msgstr "wystąpił błąd podczas aktualizacji użytkownika %s" @@ -574,44 +574,44 @@ msgstr "Wystąpił błąd w trakcie aktualizacji hasła użytkownika" #: kallithea/controllers/admin/my_account.py:209 -#: kallithea/controllers/admin/users.py:367 +#: kallithea/controllers/admin/users.py:365 #, python-format msgid "Added email %s to user" msgstr "Dodano e-mail %s do użytkownika" #: kallithea/controllers/admin/my_account.py:215 -#: kallithea/controllers/admin/users.py:373 +#: kallithea/controllers/admin/users.py:371 msgid "An error occurred during email saving" msgstr "Wystąpił błąd podczas zapisywania e-maila" #: kallithea/controllers/admin/my_account.py:224 -#: kallithea/controllers/admin/users.py:383 +#: kallithea/controllers/admin/users.py:381 msgid "Removed email from user" msgstr "Usunięto e-mail użytkownikowi" #: kallithea/controllers/admin/my_account.py:248 -#: kallithea/controllers/admin/users.py:271 +#: kallithea/controllers/admin/users.py:269 msgid "API key successfully created" msgstr "" #: kallithea/controllers/admin/my_account.py:257 -#: kallithea/controllers/admin/users.py:281 +#: kallithea/controllers/admin/users.py:279 msgid "API key successfully reset" msgstr "" #: kallithea/controllers/admin/my_account.py:261 -#: kallithea/controllers/admin/users.py:285 +#: kallithea/controllers/admin/users.py:283 msgid "API key successfully deleted" msgstr "" #: kallithea/controllers/admin/my_account.py:281 -#: kallithea/controllers/admin/users.py:456 +#: kallithea/controllers/admin/users.py:454 #, python-format msgid "SSH key %s successfully added" msgstr "" #: kallithea/controllers/admin/my_account.py:293 -#: kallithea/controllers/admin/users.py:470 +#: kallithea/controllers/admin/users.py:468 #, fuzzy #| msgid "Successfully deleted user" msgid "SSH key successfully deleted" @@ -689,11 +689,11 @@ msgid "Allowed with automatic account activation" msgstr "Dozwolona z automatyczną aktywacją konta" -#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673 +#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670 msgid "Manual activation of external account" msgstr "Ręczna aktywacja nowego konta" -#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674 +#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671 msgid "Automatic activation of external account" msgstr "Automatyczna aktywacja nowego konta" @@ -715,59 +715,59 @@ msgid "Error occurred during update of permissions" msgstr "Wystąpił błąd podczas aktualizacji uprawnień" -#: kallithea/controllers/admin/repo_groups.py:172 +#: kallithea/controllers/admin/repo_groups.py:167 #, python-format msgid "Error occurred during creation of repository group %s" msgstr "Wystąpił błąd podczas tworzenia grupy repo %s" -#: kallithea/controllers/admin/repo_groups.py:177 +#: kallithea/controllers/admin/repo_groups.py:174 #, python-format msgid "Created repository group %s" msgstr "Utworzono grupę repo %s" -#: kallithea/controllers/admin/repo_groups.py:224 +#: kallithea/controllers/admin/repo_groups.py:221 #, python-format msgid "Updated repository group %s" msgstr "Zaktualizowano grupę repo %s" -#: kallithea/controllers/admin/repo_groups.py:240 +#: kallithea/controllers/admin/repo_groups.py:237 #, python-format msgid "Error occurred during update of repository group %s" msgstr "Wystąpił błąd podczas aktualizacji grupy repo %s" -#: kallithea/controllers/admin/repo_groups.py:250 +#: kallithea/controllers/admin/repo_groups.py:247 #, python-format msgid "This group contains %s repositories and cannot be deleted" msgstr "Ta grupa zawiera %s repozytorium i nie może być usunięta" -#: kallithea/controllers/admin/repo_groups.py:257 +#: kallithea/controllers/admin/repo_groups.py:254 #, python-format msgid "This group contains %s subgroups and cannot be deleted" msgstr "Ta grupa zawiera %s repozytorium i nie może być usunięta" -#: kallithea/controllers/admin/repo_groups.py:263 +#: kallithea/controllers/admin/repo_groups.py:260 #, python-format msgid "Removed repository group %s" msgstr "Usunięto grupę repo %s" -#: kallithea/controllers/admin/repo_groups.py:268 +#: kallithea/controllers/admin/repo_groups.py:265 #, python-format msgid "Error occurred during deletion of repository group %s" msgstr "Wystąpił błąd podczas usuwania z repozytorium grupy %s" -#: kallithea/controllers/admin/repo_groups.py:352 -#: kallithea/controllers/admin/repo_groups.py:382 -#: kallithea/controllers/admin/user_groups.py:294 +#: kallithea/controllers/admin/repo_groups.py:349 +#: kallithea/controllers/admin/repo_groups.py:379 +#: kallithea/controllers/admin/user_groups.py:292 msgid "Cannot revoke permission for yourself as admin" msgstr "Nie można cofnąć zezwolenia dla admina jako admin" -#: kallithea/controllers/admin/repo_groups.py:367 +#: kallithea/controllers/admin/repo_groups.py:364 msgid "Repository group permissions updated" msgstr "Aktualizacja uprawnień grup repozytorium" -#: kallithea/controllers/admin/repo_groups.py:399 +#: kallithea/controllers/admin/repo_groups.py:396 #: kallithea/controllers/admin/repos.py:358 -#: kallithea/controllers/admin/user_groups.py:306 +#: kallithea/controllers/admin/user_groups.py:304 msgid "An error occurred during revoking of permission" msgstr "Wystąpił błąd podczas cofania zezwolenia" @@ -895,7 +895,7 @@ msgid "Updated VCS settings" msgstr "Aktualizacja ustawień VCS" -#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237 +#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238 msgid "" "Unable to activate hgsubversion support. The \"hgsubversion\" library is " "missing" @@ -962,96 +962,96 @@ msgid "Whoosh reindex task scheduled" msgstr "Zadanie ponownej indeksacji whoosh zostało zaplanowane" -#: kallithea/controllers/admin/user_groups.py:138 +#: kallithea/controllers/admin/user_groups.py:136 #, python-format msgid "Created user group %s" msgstr "Utworzono grupę użytkowników %s" -#: kallithea/controllers/admin/user_groups.py:151 +#: kallithea/controllers/admin/user_groups.py:149 #, python-format msgid "Error occurred during creation of user group %s" msgstr "Wystąpił błąd podczas tworzenia grupy użytkowników %s" -#: kallithea/controllers/admin/user_groups.py:179 +#: kallithea/controllers/admin/user_groups.py:177 #, python-format msgid "Updated user group %s" msgstr "Zaktualizowano grupę użytkowników %s" -#: kallithea/controllers/admin/user_groups.py:201 +#: kallithea/controllers/admin/user_groups.py:199 #, python-format msgid "Error occurred during update of user group %s" msgstr "Wystąpił błąd podczas aktualizacji grupy użytkowników %s" -#: kallithea/controllers/admin/user_groups.py:212 +#: kallithea/controllers/admin/user_groups.py:210 msgid "Successfully deleted user group" msgstr "Grupa użytkowników została usunięta z powodzeniem" -#: kallithea/controllers/admin/user_groups.py:217 +#: kallithea/controllers/admin/user_groups.py:215 msgid "An error occurred during deletion of user group" msgstr "Wystąpił błąd podczas usuwania grupy użytkowników" -#: kallithea/controllers/admin/user_groups.py:273 +#: kallithea/controllers/admin/user_groups.py:271 msgid "Target group cannot be the same" msgstr "Grupa docelowa nie może być taka sama" -#: kallithea/controllers/admin/user_groups.py:279 +#: kallithea/controllers/admin/user_groups.py:277 msgid "User group permissions updated" msgstr "Aktualizacja uprawnień grupy użytkowników" -#: kallithea/controllers/admin/user_groups.py:388 -#: kallithea/controllers/admin/users.py:338 +#: kallithea/controllers/admin/user_groups.py:386 +#: kallithea/controllers/admin/users.py:336 msgid "Updated permissions" msgstr "Aktualizacja uprawnień" -#: kallithea/controllers/admin/user_groups.py:392 -#: kallithea/controllers/admin/users.py:342 +#: kallithea/controllers/admin/user_groups.py:390 +#: kallithea/controllers/admin/users.py:340 msgid "An error occurred during permissions saving" msgstr "Wystąpił błąd podczas zapisywania uprawnień" -#: kallithea/controllers/admin/users.py:123 +#: kallithea/controllers/admin/users.py:121 #, python-format msgid "Created user %s" msgstr "Utworzono użytkownika %s" -#: kallithea/controllers/admin/users.py:138 +#: kallithea/controllers/admin/users.py:136 #, python-format msgid "Error occurred during creation of user %s" msgstr "Wystąpił błąd podczas tworzenia użytkownika %s" -#: kallithea/controllers/admin/users.py:162 +#: kallithea/controllers/admin/users.py:160 msgid "User updated successfully" msgstr "Użytkownik został zaktualizowany" -#: kallithea/controllers/admin/users.py:190 +#: kallithea/controllers/admin/users.py:188 msgid "Successfully deleted user" msgstr "Użytkownik został usunięty" -#: kallithea/controllers/admin/users.py:195 +#: kallithea/controllers/admin/users.py:193 msgid "An error occurred during deletion of user" msgstr "Wystąpił błąd podczas usuwania użytkownika" -#: kallithea/controllers/admin/users.py:203 +#: kallithea/controllers/admin/users.py:201 msgid "The default user cannot be edited" msgstr "" -#: kallithea/controllers/admin/users.py:409 +#: kallithea/controllers/admin/users.py:407 #, python-format msgid "Added IP address %s to user whitelist" msgstr "Dodano ip %s do listy dozwolonych adresów użytkownika" -#: kallithea/controllers/admin/users.py:415 +#: kallithea/controllers/admin/users.py:413 msgid "An error occurred while adding IP address" msgstr "Wystąpił błąd podczas zapisywania adresu IP" -#: kallithea/controllers/admin/users.py:427 +#: kallithea/controllers/admin/users.py:425 msgid "Removed IP address from user whitelist" msgstr "Usunięto adres ip z listy dozwolonych adresów dla użytkownika" -#: kallithea/lib/auth.py:684 +#: kallithea/lib/auth.py:668 msgid "You need to be a registered user to perform this action" msgstr "Musisz być zarejestrowanym użytkownikiem, żeby wykonać to działanie" -#: kallithea/lib/auth.py:712 +#: kallithea/lib/auth.py:696 msgid "You need to be signed in to view this page" msgstr "Musisz być zalogowany, żeby oglądać stronę" @@ -1087,170 +1087,170 @@ "Lista zmian była zbyt duża i została obcięta, użyj menu porównań żeby " "wyświetlić różnice" -#: kallithea/lib/diffs.py:224 +#: kallithea/lib/diffs.py:223 msgid "No changes detected" msgstr "Nie wykryto zmian" -#: kallithea/lib/helpers.py:653 +#: kallithea/lib/helpers.py:646 #, python-format msgid "Deleted branch: %s" msgstr "Usunięta gałąź: %s" -#: kallithea/lib/helpers.py:655 +#: kallithea/lib/helpers.py:648 #, python-format msgid "Created tag: %s" msgstr "Utworzony tag: %s" -#: kallithea/lib/helpers.py:666 +#: kallithea/lib/helpers.py:659 #, python-format msgid "Changeset %s not found" msgstr "Nie znaleziono changeset %s" -#: kallithea/lib/helpers.py:715 +#: kallithea/lib/helpers.py:708 #, python-format msgid "Show all combined changesets %s->%s" msgstr "Pokaż wszystkie zestawienia zmian changesets %s->%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "Wyświetl porównanie" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "i" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "%s więcej" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "rewizja" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "nazwa rozgałęzienia %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, fuzzy, python-format msgid "Pull request %s" msgstr "Połączonych gałęzi #%s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "[usunięte] repozytorium" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "[utworzone] repozytorium" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[utworzone] repozytorium jako rozgałęzienie" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "[rozgałęzione] repozytorium" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "[zaktualizowane] repozytorium" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "[pobierz] archiwum z repozytorium" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "[skasowane] repozytorium" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "[utworzony] użytkownik" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "[zaktualizowany] użytkownik" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "[utworzona] grupa użytkowników" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "[zaktualizowana] grupa użytkowników" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "[komentarz] do zmiany w repozytorium" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "[komentarz] wniosek o połączenie gałęzi" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "[zamknięty] wniosek o połączenie gałęzi" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[wysłane zmiany] w" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "[synchronizacja przez Kallithea] z repozytorium" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "[pobieranie z zdalnego] do repozytorium" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[pobrano]" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "[start następnego] repozytorium" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "[zatrzymany po] repozytorium" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " i %s więcej" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Brak plików" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "nowy plik" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "modyfikuj" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "kasuj" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "zmień nazwę" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1261,34 +1261,36 @@ "zmienione z systemie plików proszę uruchomić aplikację ponownie, aby " "ponownie przeskanować repozytoria" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" @@ -1296,7 +1298,7 @@ msgstr[1] "%d lata" msgstr[2] "%d lat" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" @@ -1304,7 +1306,7 @@ msgstr[1] "%d miesięcy" msgstr[2] "%d miesięcy" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" @@ -1312,7 +1314,7 @@ msgstr[1] "%d dni" msgstr[2] "%d dni" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" @@ -1320,7 +1322,7 @@ msgstr[1] "%d godziny" msgstr[2] "%d godzin" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" @@ -1328,7 +1330,7 @@ msgstr[1] "%d minuty" msgstr[2] "%d minut" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" @@ -1336,27 +1338,27 @@ msgstr[1] "%d sekund" msgstr[2] "%d sekund" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "w %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "%s temu" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "w %s i %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s i %s temu" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "przed chwilą" @@ -1365,144 +1367,144 @@ msgid "on line %s" msgstr "widziany %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Wymieniony]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "najwyższy poziom" -#: kallithea/model/db.py:1637 +#: kallithea/model/db.py:1634 msgid "Kallithea Administrator" msgstr "Administrator Kallithea" +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1637 +msgid "Default user has read access to new repositories" +msgstr "Użytkownik domyślny ma dostęp do odczytu nowych repozytoriów" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" +msgstr "Użytkownik domyślny ma dostęp do zapisu nowych repozytoriów" + #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" -msgstr "Użytkownik domyślny ma dostęp do odczytu nowych repozytoriów" +msgid "Default user has admin access to new repositories" +msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" -msgstr "Użytkownik domyślny ma dostęp do zapisu nowych repozytoriów" +msgid "Default user has no access to new repository groups" +msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1654 #, fuzzy msgid "Only admins can create repository groups" msgstr "Tylko admini mogą tworzyć grupy repozytoriów" -#: kallithea/model/db.py:1655 +#: kallithea/model/db.py:1652 #, fuzzy msgid "Non-admins can create repository groups" msgstr "" "Użytkownicy bez uprawnień administratora mogą tworzyć grupy repozytoriów" -#: kallithea/model/db.py:1657 +#: kallithea/model/db.py:1654 #, fuzzy msgid "Only admins can create user groups" msgstr "Tylko admini mogą tworzyć grupy użytkowników" -#: kallithea/model/db.py:1658 +#: kallithea/model/db.py:1655 #, fuzzy msgid "Non-admins can create user groups" msgstr "" "Użytkownicy bez uprawnień administratora mogą tworzyć grupy użytkowników" +#: kallithea/model/db.py:1657 +msgid "Only admins can create top level repositories" +msgstr "" + +#: kallithea/model/db.py:1658 +msgid "Non-admins can create top level repositories" +msgstr "" + #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1666 #, fuzzy msgid "Only admins can fork repositories" msgstr "Tylko admini mogą rozgałęziać repozytoria" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 #, fuzzy msgid "Non-admins can fork repositories" msgstr "" "Użytkownicy bez uprawnień administratora mogą rozgałęziać repozytoria" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "Rejestracja wyłączona" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "Rejestracja użytkownika z ręczną aktywacją konta" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "Rejestracja użytkownika z automatyczną aktywacją konta" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 msgid "Not reviewed" msgstr "Brak Korekty" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 msgid "Under review" msgstr "Objęty Przeglądem" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 #, fuzzy #| msgid "Approved" msgid "Not approved" msgstr "Niezaakceptowano" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "Zaakceptowano" @@ -1528,7 +1530,7 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, fuzzy, python-format #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s" msgid "" @@ -1536,118 +1538,118 @@ "%(branch)s" msgstr "[komentarz] wniosek o połączenie gałęzi" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "Użytkownik %(new_username)s zarejestrował się" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 #, fuzzy msgid "Closing" msgstr "Zamykanie" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, fuzzy, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" "%(user)s chce żeby przejrzeć nowe gałęzie %(pr_nice_id)s: %(pr_title)s" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 #, fuzzy #| msgid "Create Pull Request" msgid "Cannot create empty pull request" msgstr "Nie można stworzyć pustego żądania połączenia gałęzi" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 #, fuzzy #| msgid "Confirm to delete this pull request" msgid "You are not authorized to create the pull request" msgstr "Nie masz uprawnień, aby stworzyć żądanie połączenia gałęzi" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "ostatni tip" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Changeset %s not found" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Nie znaleziono changeset %s" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "nowy użytkownik się zarejestrował" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" "Nie możesz usunąć tego użytkownika ponieważ jest kluczowy dla całej " "aplikacji" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " @@ -1656,7 +1658,7 @@ "użytkownik \"%s\" wciąż posiada repozytoria następujące %s i nie może " "zostać usunięty. Zmień właściciela lub usuń te repozytoria: %s" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " @@ -1665,7 +1667,7 @@ "użytkownik \"%s\" wciąż posiada repozytoria następujące %s i nie może " "zostać usunięty. Zmień właściciela lub usuń te repozytoria: %s" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " @@ -1674,16 +1676,16 @@ "użytkownik \"%s\" wciąż posiada repozytoria następujące %s i nie może " "zostać usunięty. Zmień właściciela lub usuń te grupy użytkowników: %s" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "łącze resetowania hasła" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 #, fuzzy msgid "Password reset notification" msgstr "Powiadomienie o resetowaniu hasła" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2391,7 +2393,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3499,7 +3501,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 #, fuzzy msgid "Save Settings" msgstr "Zapisz ustawienia" @@ -3753,57 +3755,57 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repository Size" msgid "Repository page size" msgstr "Rozmiar Repozytorium" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "Ikony" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "Pokazuj w publicznym repo ikonę w repozytoriach" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "Pokazuj w prywatnym repo ikonę w repozytoriach" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 #, fuzzy msgid "Show public/private icons next to repository names." msgstr "Pokazuj ikonę publiczne/prywatne repo w repozytoriach." -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 #, fuzzy msgid "Meta Tagging" msgstr "Tagowanie meta" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4470,26 +4472,26 @@ msgid "Merge" msgstr "połącz" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 #, fuzzy msgid "Grafted from:" msgstr "Połączono z:" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 #, fuzzy msgid "Replaced by:" msgstr "Zastąpiono przez:" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 #, fuzzy msgid "Preceded by:" msgstr "Poprzedzone przez:" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4499,7 +4501,7 @@ msgstr[1] "%s pliki zostały zmienione" msgstr[2] "%s plików zostało zmienionych" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4509,8 +4511,8 @@ msgstr[1] "%s plików zostało zmienionych z %s inercjami i %s usunięciami" msgstr[2] "%s plików zostało zmienionych z %s inercjami i %s usunięciami" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5558,45 +5560,45 @@ msgid "Stats gathered: " msgstr "Statystyki zebrane: " -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "pliki" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "Pokaż więcej" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "komunikaty" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "pliki dodane" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "pliki zmienione" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "pliki usunięte" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "pliki usunięte" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "komunikaty" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "plik dodany" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "plik zmieniony" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "plik usunięty" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2014-02-13 14:34+0000\n" "Last-Translator: Marcin Kuźmiński \n" "Language-Team: Portuguese (Brazil) 1)\n" #: kallithea/controllers/changelog.py:67 -#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602 +#: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:602 msgid "There are no changesets yet" msgstr "Não há nenhum changeset ainda" #: kallithea/controllers/admin/permissions.py:64 #: kallithea/controllers/admin/permissions.py:68 #: kallithea/controllers/admin/permissions.py:72 -#: kallithea/controllers/changelog.py:137 +#: kallithea/controllers/changelog.py:136 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7 @@ -32,37 +32,37 @@ msgid "None" msgstr "Nenhum" -#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189 +#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:189 msgid "(closed)" msgstr "(fechado)" -#: kallithea/controllers/changeset.py:81 +#: kallithea/controllers/changeset.py:82 msgid "Show whitespace" msgstr "Mostrar espaços em branco" -#: kallithea/controllers/changeset.py:88 -#: kallithea/controllers/changeset.py:95 +#: kallithea/controllers/changeset.py:89 +#: kallithea/controllers/changeset.py:96 #: kallithea/templates/files/diff_2way.html:55 msgid "Ignore whitespace" msgstr "Ignorar espaços em branco" -#: kallithea/controllers/changeset.py:161 +#: kallithea/controllers/changeset.py:162 #, python-format msgid "Increase diff context to %(num)s lines" msgstr "" -#: kallithea/controllers/changeset.py:201 +#: kallithea/controllers/changeset.py:202 #, fuzzy msgid "No permission to change status" msgstr "Vote para estado do pull request" -#: kallithea/controllers/changeset.py:212 +#: kallithea/controllers/changeset.py:213 #, fuzzy, python-format msgid "Successfully deleted pull request %s" msgstr "Pull request excluído com sucesso" -#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89 -#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700 +#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89 +#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697 msgid "Such revision does not exist for this repository" msgstr "" @@ -76,51 +76,51 @@ msgid "Cannot compare repositories of different types" msgstr "" -#: kallithea/controllers/compare.py:246 +#: kallithea/controllers/compare.py:247 msgid "Cannot show empty diff" msgstr "" -#: kallithea/controllers/compare.py:248 +#: kallithea/controllers/compare.py:249 msgid "No ancestor found for merge diff" msgstr "" -#: kallithea/controllers/compare.py:252 +#: kallithea/controllers/compare.py:253 msgid "Multiple merge ancestors found for merge compare" msgstr "" -#: kallithea/controllers/compare.py:268 +#: kallithea/controllers/compare.py:269 msgid "Cannot compare repositories without using common ancestor" msgstr "" -#: kallithea/controllers/error.py:71 +#: kallithea/controllers/error.py:70 #, fuzzy msgid "No response" msgstr "revisões" -#: kallithea/controllers/error.py:72 +#: kallithea/controllers/error.py:71 msgid "Unknown error" msgstr "" -#: kallithea/controllers/error.py:85 +#: kallithea/controllers/error.py:84 msgid "" "The request could not be understood by the server due to malformed syntax." msgstr "" "A requisição não pôde ser compreendida pelo servidor devido à sintaxe mal " "formada." -#: kallithea/controllers/error.py:88 +#: kallithea/controllers/error.py:87 msgid "Unauthorized access to resource" msgstr "Acesso não autorizado ao recurso" -#: kallithea/controllers/error.py:90 +#: kallithea/controllers/error.py:89 msgid "You don't have permission to view this page" msgstr "Você não tem permissão para ver esta página" -#: kallithea/controllers/error.py:92 +#: kallithea/controllers/error.py:91 msgid "The resource could not be found" msgstr "O recurso não pôde ser encontrado" -#: kallithea/controllers/error.py:94 +#: kallithea/controllers/error.py:93 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." @@ -128,14 +128,14 @@ "O servidor encontrou uma condição inesperada que o impediu de satisfazer " "a requisição." -#: kallithea/controllers/feed.py:63 +#: kallithea/controllers/feed.py:59 #, python-format msgid "%s committed on %s" msgstr "%s commitados em %s" -#: kallithea/controllers/feed.py:88 -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/controllers/feed.py:84 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/compare/compare_diff.html:95 #: kallithea/templates/pullrequests/pullrequest_show.html:309 @@ -143,12 +143,12 @@ msgid "Changeset was too big and was cut off..." msgstr "Conjunto de mudanças era grande demais e foi cortado..." -#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140 +#: kallithea/controllers/feed.py:107 #, python-format msgid "%s %s feed" msgstr "%s - feed %s" -#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142 +#: kallithea/controllers/feed.py:109 #, python-format msgid "Changes on %s repository" msgstr "Modificações no repositório %s" @@ -168,92 +168,92 @@ msgid "%s at %s" msgstr "em %s e %s" -#: kallithea/controllers/files.py:296 +#: kallithea/controllers/files.py:295 #, fuzzy msgid "You can only delete files with revision being a valid branch" msgstr "Só é possível editar arquivos quando a revisão é um ramo válido" -#: kallithea/controllers/files.py:307 +#: kallithea/controllers/files.py:306 #, python-format msgid "Deleted file %s via Kallithea" msgstr "" -#: kallithea/controllers/files.py:331 +#: kallithea/controllers/files.py:330 #, python-format msgid "Successfully deleted file %s" msgstr "" -#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394 -#: kallithea/controllers/files.py:469 +#: kallithea/controllers/files.py:334 kallithea/controllers/files.py:392 +#: kallithea/controllers/files.py:467 msgid "Error occurred during commit" msgstr "Ocorreu um erro ao realizar commit" -#: kallithea/controllers/files.py:350 +#: kallithea/controllers/files.py:349 #, fuzzy msgid "You can only edit files with revision being a valid branch" msgstr "Só é possível editar arquivos quando a revisão é um ramo válido" -#: kallithea/controllers/files.py:364 +#: kallithea/controllers/files.py:363 #, python-format msgid "Edited file %s via Kallithea" msgstr "Arquivo %s editado via Kallithea" -#: kallithea/controllers/files.py:380 +#: kallithea/controllers/files.py:378 msgid "No changes" msgstr "Sem modificações" -#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458 +#: kallithea/controllers/files.py:388 kallithea/controllers/files.py:456 #, python-format msgid "Successfully committed to %s" msgstr "Commit realizado com sucesso para %s" -#: kallithea/controllers/files.py:409 +#: kallithea/controllers/files.py:407 msgid "Added file via Kallithea" msgstr "Arquivo adicionado via Kallithea" -#: kallithea/controllers/files.py:430 +#: kallithea/controllers/files.py:428 msgid "No content" msgstr "Nenhum conteúdo" -#: kallithea/controllers/files.py:434 +#: kallithea/controllers/files.py:432 msgid "No filename" msgstr "Nenhum nome de arquivo" -#: kallithea/controllers/files.py:461 +#: kallithea/controllers/files.py:459 msgid "Location must be relative path and must not contain .. in path" msgstr "O caminho deve ser relativo e não pode conter .." -#: kallithea/controllers/files.py:493 +#: kallithea/controllers/files.py:491 msgid "Downloads disabled" msgstr "Downloads desabilitados" -#: kallithea/controllers/files.py:504 +#: kallithea/controllers/files.py:502 #, python-format msgid "Unknown revision %s" msgstr "Revisão desconhecida %s" -#: kallithea/controllers/files.py:506 +#: kallithea/controllers/files.py:504 msgid "Empty repository" msgstr "Repositório vazio" -#: kallithea/controllers/files.py:508 +#: kallithea/controllers/files.py:506 msgid "Unknown archive type" msgstr "Tipo de arquivo desconhecido" -#: kallithea/controllers/files.py:729 +#: kallithea/controllers/files.py:726 #: kallithea/templates/changeset/changeset_range.html:9 #: kallithea/templates/email_templates/pull_request.html:64 #: kallithea/templates/pullrequests/pullrequest.html:84 msgid "Changesets" msgstr "Conjuntos de mudanças" -#: kallithea/controllers/files.py:730 -#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676 +#: kallithea/controllers/files.py:727 +#: kallithea/controllers/pullrequests.py:174 kallithea/model/scm.py:663 msgid "Branches" msgstr "Ramos" -#: kallithea/controllers/files.py:731 -#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687 +#: kallithea/controllers/files.py:728 +#: kallithea/controllers/pullrequests.py:175 kallithea/model/scm.py:674 msgid "Tags" msgstr "Etiquetas" @@ -262,11 +262,11 @@ msgid "An error occurred during repository forking %s" msgstr "Ocorreu um erro ao bifurcar o repositório %s" -#: kallithea/controllers/home.py:79 +#: kallithea/controllers/home.py:77 msgid "Groups" msgstr "" -#: kallithea/controllers/home.py:89 +#: kallithea/controllers/home.py:87 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90 #: kallithea/templates/admin/repos/repo_add.html:12 #: kallithea/templates/admin/repos/repo_add.html:16 @@ -278,203 +278,203 @@ msgid "Repositories" msgstr "Repositórios" -#: kallithea/controllers/home.py:122 +#: kallithea/controllers/home.py:119 #: kallithea/templates/files/files_add.html:32 #: kallithea/templates/files/files_delete.html:23 #: kallithea/templates/files/files_edit.html:32 msgid "Branch" msgstr "Ramo" -#: kallithea/controllers/home.py:128 +#: kallithea/controllers/home.py:125 msgid "Closed Branches" msgstr "Ramos Fechados" -#: kallithea/controllers/home.py:134 +#: kallithea/controllers/home.py:131 msgid "Tag" msgstr "" -#: kallithea/controllers/home.py:140 +#: kallithea/controllers/home.py:137 msgid "Bookmark" msgstr "" -#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154 +#: kallithea/controllers/journal.py:146 kallithea/controllers/journal.py:157 #: kallithea/templates/journal/public_journal.html:4 #: kallithea/templates/journal/public_journal.html:18 msgid "Public Journal" msgstr "Diário Público" -#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158 +#: kallithea/controllers/journal.py:150 kallithea/controllers/journal.py:161 #: kallithea/templates/base/base.html:290 #: kallithea/templates/journal/journal.html:5 #: kallithea/templates/journal/journal.html:13 msgid "Journal" msgstr "Diário" -#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185 +#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184 msgid "Bad captcha" msgstr "" -#: kallithea/controllers/login.py:146 +#: kallithea/controllers/login.py:145 #, python-format msgid "You have successfully registered with %s" msgstr "Você foi registrado no %s com sucesso" -#: kallithea/controllers/login.py:190 +#: kallithea/controllers/login.py:189 #, fuzzy msgid "A password reset confirmation code has been sent" msgstr "Seu link de reinicialização de senha foi enviado" -#: kallithea/controllers/login.py:239 +#: kallithea/controllers/login.py:236 #, fuzzy msgid "Invalid password reset token" msgstr "Link para trocar senha" #: kallithea/controllers/admin/my_account.py:157 -#: kallithea/controllers/login.py:244 +#: kallithea/controllers/login.py:241 msgid "Successfully updated password" msgstr "" -#: kallithea/controllers/pullrequests.py:68 +#: kallithea/controllers/pullrequests.py:67 #, python-format msgid "Invalid reviewer \"%s\" specified" msgstr "" -#: kallithea/controllers/pullrequests.py:131 +#: kallithea/controllers/pullrequests.py:123 #, python-format msgid "%s (closed)" msgstr "" -#: kallithea/controllers/pullrequests.py:158 +#: kallithea/controllers/pullrequests.py:150 #: kallithea/templates/changeset/changeset.html:12 msgid "Changeset" msgstr "Conjunto de Mudanças" -#: kallithea/controllers/pullrequests.py:179 +#: kallithea/controllers/pullrequests.py:171 msgid "Special" msgstr "Especial" -#: kallithea/controllers/pullrequests.py:180 +#: kallithea/controllers/pullrequests.py:172 msgid "Peer branches" msgstr "Ramos pares" -#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682 +#: kallithea/controllers/pullrequests.py:173 kallithea/model/scm.py:669 msgid "Bookmarks" msgstr "Marcadores" -#: kallithea/controllers/pullrequests.py:318 +#: kallithea/controllers/pullrequests.py:315 #, python-format msgid "Error creating pull request: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:345 -#: kallithea/controllers/pullrequests.py:368 +#: kallithea/controllers/pullrequests.py:342 +#: kallithea/controllers/pullrequests.py:365 #, fuzzy msgid "Error occurred while creating pull request" msgstr "Ocorreu um erro durante o envio do pull request" -#: kallithea/controllers/pullrequests.py:350 +#: kallithea/controllers/pullrequests.py:347 msgid "Successfully opened new pull request" msgstr "Novo pull request criado com sucesso" -#: kallithea/controllers/pullrequests.py:373 +#: kallithea/controllers/pullrequests.py:370 #, fuzzy #| msgid "Pull request update created" msgid "New pull request iteration created" msgstr "Revisores do pull request" -#: kallithea/controllers/pullrequests.py:401 +#: kallithea/controllers/pullrequests.py:398 #, python-format msgid "Meanwhile, the following reviewers have been added: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:405 +#: kallithea/controllers/pullrequests.py:402 #, python-format msgid "Meanwhile, the following reviewers have been removed: %s" msgstr "" -#: kallithea/controllers/pullrequests.py:421 -#: kallithea/model/pull_request.py:232 +#: kallithea/controllers/pullrequests.py:418 +#: kallithea/model/pull_request.py:230 #, fuzzy msgid "No description" msgstr "Descrição" -#: kallithea/controllers/pullrequests.py:430 +#: kallithea/controllers/pullrequests.py:427 #, fuzzy msgid "Pull request updated" msgstr "Pull requests para %s" -#: kallithea/controllers/pullrequests.py:443 +#: kallithea/controllers/pullrequests.py:440 msgid "Successfully deleted pull request" msgstr "Pull request excluído com sucesso" -#: kallithea/controllers/pullrequests.py:479 +#: kallithea/controllers/pullrequests.py:476 #, python-format msgid "Revision %s not found in %s" msgstr "" -#: kallithea/controllers/pullrequests.py:506 +#: kallithea/controllers/pullrequests.py:504 #, python-format msgid "Error: changesets not found when displaying pull request from %s." msgstr "" +#: kallithea/controllers/pullrequests.py:518 +#, python-format +msgid "This pull request has already been merged to %s." +msgstr "" + #: kallithea/controllers/pullrequests.py:520 -#, python-format -msgid "This pull request has already been merged to %s." -msgstr "" - -#: kallithea/controllers/pullrequests.py:522 msgid "This pull request has been closed and can not be updated." msgstr "" -#: kallithea/controllers/pullrequests.py:546 +#: kallithea/controllers/pullrequests.py:539 #, python-format msgid "The following additional changes are available on %s:" msgstr "" -#: kallithea/controllers/pullrequests.py:548 -#: kallithea/controllers/pullrequests.py:552 +#: kallithea/controllers/pullrequests.py:541 +#: kallithea/controllers/pullrequests.py:545 msgid "No additional changesets found for iterating on this pull request." msgstr "" +#: kallithea/controllers/pullrequests.py:553 +#, python-format +msgid "Note: Branch %s has another head: %s." +msgstr "" + #: kallithea/controllers/pullrequests.py:560 -#, python-format -msgid "Note: Branch %s has another head: %s." -msgstr "" - -#: kallithea/controllers/pullrequests.py:567 msgid "Git pull requests don't support iterating yet." msgstr "" -#: kallithea/controllers/pullrequests.py:569 +#: kallithea/controllers/pullrequests.py:562 #, python-format msgid "" "Error: some changesets not found when displaying pull request from %s." msgstr "" -#: kallithea/controllers/pullrequests.py:593 +#: kallithea/controllers/pullrequests.py:586 msgid "The diff can't be shown - the PR revisions could not be found." msgstr "" -#: kallithea/controllers/search.py:136 +#: kallithea/controllers/search.py:132 msgid "Invalid search query. Try quoting it." msgstr "Consulta de busca inválida. Tente usar aspas." -#: kallithea/controllers/search.py:140 +#: kallithea/controllers/search.py:136 msgid "The server has no search index." msgstr "" -#: kallithea/controllers/search.py:143 +#: kallithea/controllers/search.py:139 #, fuzzy msgid "An error occurred during search operation." msgstr "Ocorreu um erro durante essa operação de busca" -#: kallithea/controllers/summary.py:168 -#: kallithea/templates/summary/summary.html:412 +#: kallithea/controllers/summary.py:169 +#: kallithea/templates/summary/summary.html:410 #, fuzzy msgid "No data ready yet" msgstr "Ainda não há dados carregados" -#: kallithea/controllers/summary.py:171 +#: kallithea/controllers/summary.py:172 #: kallithea/templates/summary/summary.html:97 msgid "Statistics are disabled for this repository" msgstr "As estatísticas estão desabillitadas para este repositório" @@ -487,82 +487,82 @@ msgid "error occurred during update of auth settings" msgstr "" -#: kallithea/controllers/admin/defaults.py:75 +#: kallithea/controllers/admin/defaults.py:74 msgid "Default settings updated successfully" msgstr "Configurações padrão atualizadas com sucesso" -#: kallithea/controllers/admin/defaults.py:90 +#: kallithea/controllers/admin/defaults.py:89 msgid "Error occurred during update of defaults" msgstr "Ocorreu um erro durnge a atualização dos padrões" #: kallithea/controllers/admin/gists.py:59 #: kallithea/controllers/admin/my_account.py:232 -#: kallithea/controllers/admin/users.py:248 +#: kallithea/controllers/admin/users.py:246 #, fuzzy msgid "Forever" msgstr "para sempre" #: kallithea/controllers/admin/gists.py:60 #: kallithea/controllers/admin/my_account.py:233 -#: kallithea/controllers/admin/users.py:249 +#: kallithea/controllers/admin/users.py:247 msgid "5 minutes" msgstr "cinco minutos" #: kallithea/controllers/admin/gists.py:61 #: kallithea/controllers/admin/my_account.py:234 -#: kallithea/controllers/admin/users.py:250 +#: kallithea/controllers/admin/users.py:248 msgid "1 hour" msgstr "uma hora" #: kallithea/controllers/admin/gists.py:62 #: kallithea/controllers/admin/my_account.py:235 -#: kallithea/controllers/admin/users.py:251 +#: kallithea/controllers/admin/users.py:249 msgid "1 day" msgstr "um dia" #: kallithea/controllers/admin/gists.py:63 #: kallithea/controllers/admin/my_account.py:236 -#: kallithea/controllers/admin/users.py:252 +#: kallithea/controllers/admin/users.py:250 msgid "1 month" msgstr "um mês" #: kallithea/controllers/admin/gists.py:67 #: kallithea/controllers/admin/my_account.py:238 -#: kallithea/controllers/admin/users.py:254 +#: kallithea/controllers/admin/users.py:252 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65 #: kallithea/templates/admin/users/user_edit_api_keys.html:65 msgid "Lifetime" msgstr "" -#: kallithea/controllers/admin/gists.py:142 +#: kallithea/controllers/admin/gists.py:148 msgid "Error occurred during gist creation" msgstr "Ocorreu um erro durante a criação de um gist" -#: kallithea/controllers/admin/gists.py:158 +#: kallithea/controllers/admin/gists.py:164 #, python-format msgid "Deleted gist %s" msgstr "Gist %s excluído" -#: kallithea/controllers/admin/gists.py:198 +#: kallithea/controllers/admin/gists.py:207 #, fuzzy msgid "Unmodified" msgstr "Última alteração" -#: kallithea/controllers/admin/gists.py:228 +#: kallithea/controllers/admin/gists.py:237 msgid "Successfully updated gist content" msgstr "" -#: kallithea/controllers/admin/gists.py:233 +#: kallithea/controllers/admin/gists.py:242 msgid "Successfully updated gist data" msgstr "" -#: kallithea/controllers/admin/gists.py:236 +#: kallithea/controllers/admin/gists.py:245 #, python-format msgid "Error occurred during update of gist %s" msgstr "" -#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211 -#: kallithea/model/user.py:232 +#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209 +#: kallithea/model/user.py:230 msgid "You can't edit this user since it's crucial for entire application" msgstr "" "Você não pode editar esse usuário pois ele é crucial para toda a aplicação" @@ -572,7 +572,7 @@ msgstr "Sua conta foi atualizada com sucesso" #: kallithea/controllers/admin/my_account.py:134 -#: kallithea/controllers/admin/users.py:181 +#: kallithea/controllers/admin/users.py:179 #, python-format msgid "Error occurred during update of user %s" msgstr "Ocorreu um erro durante a atualização do usuário %s" @@ -582,44 +582,44 @@ msgstr "" #: kallithea/controllers/admin/my_account.py:209 -#: kallithea/controllers/admin/users.py:367 +#: kallithea/controllers/admin/users.py:365 #, python-format msgid "Added email %s to user" msgstr "Email %s adicionado ao usuário" #: kallithea/controllers/admin/my_account.py:215 -#: kallithea/controllers/admin/users.py:373 +#: kallithea/controllers/admin/users.py:371 msgid "An error occurred during email saving" msgstr "Ocorreu um erro durante o salvamento do email" #: kallithea/controllers/admin/my_account.py:224 -#: kallithea/controllers/admin/users.py:383 +#: kallithea/controllers/admin/users.py:381 msgid "Removed email from user" msgstr "Email removido do usuário" #: kallithea/controllers/admin/my_account.py:248 -#: kallithea/controllers/admin/users.py:271 +#: kallithea/controllers/admin/users.py:269 msgid "API key successfully created" msgstr "" #: kallithea/controllers/admin/my_account.py:257 -#: kallithea/controllers/admin/users.py:281 +#: kallithea/controllers/admin/users.py:279 msgid "API key successfully reset" msgstr "" #: kallithea/controllers/admin/my_account.py:261 -#: kallithea/controllers/admin/users.py:285 +#: kallithea/controllers/admin/users.py:283 msgid "API key successfully deleted" msgstr "" #: kallithea/controllers/admin/my_account.py:281 -#: kallithea/controllers/admin/users.py:456 +#: kallithea/controllers/admin/users.py:454 #, python-format msgid "SSH key %s successfully added" msgstr "" #: kallithea/controllers/admin/my_account.py:293 -#: kallithea/controllers/admin/users.py:470 +#: kallithea/controllers/admin/users.py:468 #, fuzzy #| msgid "Successfully deleted user" msgid "SSH key successfully deleted" @@ -697,11 +697,11 @@ msgid "Allowed with automatic account activation" msgstr "Permitido com ativação automática de conta" -#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673 +#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670 msgid "Manual activation of external account" msgstr "Ativação manual de conta externa" -#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674 +#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671 msgid "Automatic activation of external account" msgstr "Ativação automática de conta externa" @@ -723,59 +723,59 @@ msgid "Error occurred during update of permissions" msgstr "Ocorreu um erro durante a atualização das permissões" -#: kallithea/controllers/admin/repo_groups.py:172 +#: kallithea/controllers/admin/repo_groups.py:167 #, python-format msgid "Error occurred during creation of repository group %s" msgstr "Ocorreu um erro durante a criação do grupo de repositórios %s" -#: kallithea/controllers/admin/repo_groups.py:177 +#: kallithea/controllers/admin/repo_groups.py:174 #, python-format msgid "Created repository group %s" msgstr "Grupo de repositórios %s criado" -#: kallithea/controllers/admin/repo_groups.py:224 +#: kallithea/controllers/admin/repo_groups.py:221 #, python-format msgid "Updated repository group %s" msgstr "Grupo de repositórios %s atualizado" -#: kallithea/controllers/admin/repo_groups.py:240 +#: kallithea/controllers/admin/repo_groups.py:237 #, python-format msgid "Error occurred during update of repository group %s" msgstr "Ocorreu um erro durante a atualização do grupo de repositórios %s" -#: kallithea/controllers/admin/repo_groups.py:250 +#: kallithea/controllers/admin/repo_groups.py:247 #, python-format msgid "This group contains %s repositories and cannot be deleted" msgstr "Esse grupo contém %s repositórios e não pode ser excluído" -#: kallithea/controllers/admin/repo_groups.py:257 +#: kallithea/controllers/admin/repo_groups.py:254 #, python-format msgid "This group contains %s subgroups and cannot be deleted" msgstr "Este grupo contém %s subgrupos e não pode ser excluído" -#: kallithea/controllers/admin/repo_groups.py:263 +#: kallithea/controllers/admin/repo_groups.py:260 #, python-format msgid "Removed repository group %s" msgstr "Grupo de repositórios %s excluído" -#: kallithea/controllers/admin/repo_groups.py:268 +#: kallithea/controllers/admin/repo_groups.py:265 #, python-format msgid "Error occurred during deletion of repository group %s" msgstr "Ocorreu um erro durante a exclusão do grupo de repositórios %s" -#: kallithea/controllers/admin/repo_groups.py:352 -#: kallithea/controllers/admin/repo_groups.py:382 -#: kallithea/controllers/admin/user_groups.py:294 +#: kallithea/controllers/admin/repo_groups.py:349 +#: kallithea/controllers/admin/repo_groups.py:379 +#: kallithea/controllers/admin/user_groups.py:292 msgid "Cannot revoke permission for yourself as admin" msgstr "Você não pode revocar sua própria permissão de administrador" -#: kallithea/controllers/admin/repo_groups.py:367 +#: kallithea/controllers/admin/repo_groups.py:364 msgid "Repository group permissions updated" msgstr "Permissões atualizadas do Grupo de Repositórios" -#: kallithea/controllers/admin/repo_groups.py:399 +#: kallithea/controllers/admin/repo_groups.py:396 #: kallithea/controllers/admin/repos.py:358 -#: kallithea/controllers/admin/user_groups.py:306 +#: kallithea/controllers/admin/user_groups.py:304 msgid "An error occurred during revoking of permission" msgstr "Ocorreu um erro durante a revocação das permissões" @@ -903,7 +903,7 @@ msgid "Updated VCS settings" msgstr "Configurações de VCS atualizadas" -#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237 +#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238 msgid "" "Unable to activate hgsubversion support. The \"hgsubversion\" library is " "missing" @@ -972,96 +972,96 @@ msgid "Whoosh reindex task scheduled" msgstr "Tarefa de reindexação do whoosh agendada" -#: kallithea/controllers/admin/user_groups.py:138 +#: kallithea/controllers/admin/user_groups.py:136 #, python-format msgid "Created user group %s" msgstr "Grupo de usuários %s criado" -#: kallithea/controllers/admin/user_groups.py:151 +#: kallithea/controllers/admin/user_groups.py:149 #, python-format msgid "Error occurred during creation of user group %s" msgstr "Ocorreu um erro durante a criação do grupo de usuários %s" -#: kallithea/controllers/admin/user_groups.py:179 +#: kallithea/controllers/admin/user_groups.py:177 #, python-format msgid "Updated user group %s" msgstr "Grupo de usuários %s atualizado" -#: kallithea/controllers/admin/user_groups.py:201 +#: kallithea/controllers/admin/user_groups.py:199 #, python-format msgid "Error occurred during update of user group %s" msgstr "Ocorreu um erro durante a atualização do grupo de usuários %s" -#: kallithea/controllers/admin/user_groups.py:212 +#: kallithea/controllers/admin/user_groups.py:210 msgid "Successfully deleted user group" msgstr "Grupo de usuários excluído com sucesso" -#: kallithea/controllers/admin/user_groups.py:217 +#: kallithea/controllers/admin/user_groups.py:215 msgid "An error occurred during deletion of user group" msgstr "Ocorreu um erro durante a exclusão do grupo de usuários" -#: kallithea/controllers/admin/user_groups.py:273 +#: kallithea/controllers/admin/user_groups.py:271 msgid "Target group cannot be the same" msgstr "O grupo destino não pode ser o mesmo" -#: kallithea/controllers/admin/user_groups.py:279 +#: kallithea/controllers/admin/user_groups.py:277 msgid "User group permissions updated" msgstr "Permissões do Grupo de Usuários atualizadas" -#: kallithea/controllers/admin/user_groups.py:388 -#: kallithea/controllers/admin/users.py:338 +#: kallithea/controllers/admin/user_groups.py:386 +#: kallithea/controllers/admin/users.py:336 msgid "Updated permissions" msgstr "Permissões atualizadas" -#: kallithea/controllers/admin/user_groups.py:392 -#: kallithea/controllers/admin/users.py:342 +#: kallithea/controllers/admin/user_groups.py:390 +#: kallithea/controllers/admin/users.py:340 msgid "An error occurred during permissions saving" msgstr "Ocorreu um erro durante o salvamento das permissões" -#: kallithea/controllers/admin/users.py:123 +#: kallithea/controllers/admin/users.py:121 #, python-format msgid "Created user %s" msgstr "Usuário %s criado" -#: kallithea/controllers/admin/users.py:138 +#: kallithea/controllers/admin/users.py:136 #, python-format msgid "Error occurred during creation of user %s" msgstr "Ocorreu um erro durante a criação do usuário %s" -#: kallithea/controllers/admin/users.py:162 +#: kallithea/controllers/admin/users.py:160 msgid "User updated successfully" msgstr "Usuário atualizado com sucesso" -#: kallithea/controllers/admin/users.py:190 +#: kallithea/controllers/admin/users.py:188 msgid "Successfully deleted user" msgstr "Usuário excluído com sucesso" -#: kallithea/controllers/admin/users.py:195 +#: kallithea/controllers/admin/users.py:193 msgid "An error occurred during deletion of user" msgstr "Ocorreu um erro ao excluir o usuário" -#: kallithea/controllers/admin/users.py:203 +#: kallithea/controllers/admin/users.py:201 msgid "The default user cannot be edited" msgstr "" -#: kallithea/controllers/admin/users.py:409 +#: kallithea/controllers/admin/users.py:407 #, python-format msgid "Added IP address %s to user whitelist" msgstr "" -#: kallithea/controllers/admin/users.py:415 +#: kallithea/controllers/admin/users.py:413 msgid "An error occurred while adding IP address" msgstr "Ocorreu um erro durante o salvamento do IP" -#: kallithea/controllers/admin/users.py:427 +#: kallithea/controllers/admin/users.py:425 msgid "Removed IP address from user whitelist" msgstr "" -#: kallithea/lib/auth.py:684 +#: kallithea/lib/auth.py:668 msgid "You need to be a registered user to perform this action" msgstr "Você precisa ser um usuário registrado para realizar essa ação" -#: kallithea/lib/auth.py:712 +#: kallithea/lib/auth.py:696 msgid "You need to be signed in to view this page" msgstr "Você precisa estar logado para ver essa página" @@ -1097,172 +1097,172 @@ "Conjunto de mudanças é grande demais e foi cortado, use o menu de " "diferenças para ver as diferenças" -#: kallithea/lib/diffs.py:224 +#: kallithea/lib/diffs.py:223 msgid "No changes detected" msgstr "Nenhuma alteração detectada" -#: kallithea/lib/helpers.py:653 +#: kallithea/lib/helpers.py:646 #, python-format msgid "Deleted branch: %s" msgstr "Excluído ramo: %s" -#: kallithea/lib/helpers.py:655 +#: kallithea/lib/helpers.py:648 #, python-format msgid "Created tag: %s" msgstr "Tag criada: %s" -#: kallithea/lib/helpers.py:666 +#: kallithea/lib/helpers.py:659 #, fuzzy, python-format #| msgid "Changeset not found" msgid "Changeset %s not found" msgstr "Conjunto de alterações não encontrado" -#: kallithea/lib/helpers.py:715 +#: kallithea/lib/helpers.py:708 #, python-format msgid "Show all combined changesets %s->%s" msgstr "Ver todos os conjuntos de mudanças combinados %s->%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 #, fuzzy msgid "Compare view" msgstr "comparar exibir" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "e" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "%s mais" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "revisões" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, fuzzy, python-format msgid "Fork name %s" msgstr "nome da bifurcação %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, fuzzy, python-format msgid "Pull request %s" msgstr "Pull request #%s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "repositório [excluído]" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "repositório [criado]" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "repositório [criado] como uma bifurcação" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "repositório [bifurcado]" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "repositório [atualizado]" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "[baixado] archive do repositório" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "[excluir] repositório" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "usuário [criado]" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "usuário [atualizado]" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "[criado] grupo de usuários" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "[atualizado] grupo de usuários" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "[comentado] em revisão no repositório" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "[comentado] no pull request para" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "[fechado] pull request para" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[realizado push] para" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "[commitado via Kallithea] no repositório" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "[pulled do remote] no repositório" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[realizado pull] a partir de" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "[passou a seguir] o repositório" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "[parou de seguir] o repositório" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " e mais %s" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Nenhum arquivo" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "novo arquivo" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "mod" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "excluir" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "renomear" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1273,96 +1273,98 @@ "renomeado a partir do sistema de arquivos. Por favor, execute a aplicação " "outra vez para varrer novamente por repositórios" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d ano" msgstr[1] "%d anos" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d mês" msgstr[1] "%d meses" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dia" msgstr[1] "%d dias" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hora" msgstr[1] "%d horas" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minutos" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "em %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "%s atrás" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "em %s e %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s e %s atrás" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "agora há pouco" @@ -1371,147 +1373,147 @@ msgid "on line %s" msgstr "na linha %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Menção]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "nível superior" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "Administrador do Kallithea" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" -msgstr "Administrador do Kallithea" - -#: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 #, fuzzy msgid "Default user has read access to new repositories" msgstr "Acesso não autorizado ao recurso" -#: kallithea/model/db.py:1641 +#: kallithea/model/db.py:1638 #, fuzzy msgid "Default user has write access to new repositories" msgstr "Acesso não autorizado ao recurso" +#: kallithea/model/db.py:1639 +msgid "Default user has admin access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1641 +msgid "Default user has no access to new repository groups" +msgstr "" + #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1654 #, fuzzy msgid "Only admins can create repository groups" msgstr "Grupo de repositórios %s criado" -#: kallithea/model/db.py:1655 +#: kallithea/model/db.py:1652 #, fuzzy msgid "Non-admins can create repository groups" msgstr "Grupo de repositórios %s criado" -#: kallithea/model/db.py:1657 +#: kallithea/model/db.py:1654 #, fuzzy msgid "Only admins can create user groups" msgstr "Criar grupos de usuários" -#: kallithea/model/db.py:1658 +#: kallithea/model/db.py:1655 #, fuzzy msgid "Non-admins can create user groups" msgstr "Criar grupos de usuários" +#: kallithea/model/db.py:1657 +msgid "Only admins can create top level repositories" +msgstr "" + +#: kallithea/model/db.py:1658 +msgid "Non-admins can create top level repositories" +msgstr "" + #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1666 #, fuzzy msgid "Only admins can fork repositories" msgstr "Criar repositórios" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 #, fuzzy msgid "Non-admins can fork repositories" msgstr "Invalidar o cache para todos os repositórios" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "Registro desatilitado" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 #, fuzzy msgid "User registration with manual account activation" msgstr "Registro de Usuário com ativação manual de conta" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 #, fuzzy msgid "User registration with automatic account activation" msgstr "Registro de Usuário com ativação automática de conta" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 #, fuzzy msgid "Not reviewed" msgstr "Não Revisado" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 #, fuzzy msgid "Under review" msgstr "Sob Revisão" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 #, fuzzy #| msgid "Approved" msgid "Not approved" msgstr "Aprovado" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "Aprovado" @@ -1537,7 +1539,7 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, fuzzy, python-format #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s" msgid "" @@ -1545,111 +1547,111 @@ "%(branch)s" msgstr "[comentado] no pull request para" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, fuzzy, python-format msgid "New user %(new_username)s registered" msgstr "O username \"%(new_username)s\" não é válido" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 #, fuzzy msgid "Closing" msgstr "Usando" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, fuzzy, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" "%(user)s solicita sua revisão no pull request $%(pr_id)s: %(pr_title)s" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 #, fuzzy #| msgid "Create Pull Request" msgid "Cannot create empty pull request" msgstr "Criar Pull Request" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 #, fuzzy #| msgid "Confirm to delete this pull request" msgid "You are not authorized to create the pull request" msgstr "Confirme para excluir este pull request" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "tip mais recente" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Changeset not found" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Conjunto de alterações não encontrado" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "Novo registro de usuário" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 #, fuzzy msgid "" "You can't remove this user since it is crucial for the entire application" @@ -1657,7 +1659,7 @@ "Você não pode remover esse usuário, pois ele é crucial para toda a " "aplicação" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " @@ -1666,7 +1668,7 @@ "usuário \"%s\" ainda é dono de %s repositórios e não pode ser removido. " "Troque os donos ou remova esses repositórios. %s" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " @@ -1675,7 +1677,7 @@ "usuário \"%s\" ainda é dono de %s repositórios e não pode ser removido. " "Troque os donos ou remova esses repositórios. %s" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " @@ -1684,16 +1686,16 @@ "usuário \"%s\" ainda é dono de %s repositórios e não pode ser removido. " "Troque os donos ou remova esses repositórios. %s" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "Link para trocar senha" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 #, fuzzy msgid "Password reset notification" msgstr "Link para trocar senha" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2407,7 +2409,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3531,7 +3533,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 #, fuzzy msgid "Save Settings" msgstr "Salvar configurações" @@ -3784,57 +3786,57 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repository Size" msgid "Repository page size" msgstr "Tamanho do Repositório" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "Ícones" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "Mostrar ícone de repositório público nos repositórios" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "Mostrar ícone de repositório privado nos repositórios" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 #, fuzzy msgid "Show public/private icons next to repository names." msgstr "Mostrar ícone de repositório público nos repositórios" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 #, fuzzy msgid "Meta Tagging" msgstr "Meta-Tagging" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4502,26 +4504,26 @@ msgid "Merge" msgstr "mesclar" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 #, fuzzy msgid "Grafted from:" msgstr "Criado em" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 #, fuzzy msgid "Replaced by:" msgstr "criado" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 #, fuzzy msgid "Preceded by:" msgstr "criado" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4530,7 +4532,7 @@ msgstr[0] "%s arquivo modificado" msgstr[1] "%s arquivos modificados" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4539,8 +4541,8 @@ msgstr[0] "%s arquivo modificado com %s inserções e %s exclusões" msgstr[1] "%s arquivos modificados com %s inserções e %s exclusões" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5582,45 +5584,45 @@ msgid "Stats gathered: " msgstr "Estatísticas coletadas:" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "arquivos" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "Mostrar mais" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "commits" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "arquivos adicionados" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "arquivos alterados" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "arquivos removidos" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "arquivos removidos" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "commit" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "arquivo adicionado" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "arquivo alterado" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "arquivo removido" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/ru/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/ru/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/ru/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-12-03 08:05+0000\n" "Last-Translator: Private \n" "Language-Team: Russian =2 && n%10<=" -"4 && (n%100<10 || n%100>=20) ? 1 : 2;\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 3.10-dev\n" #: kallithea/controllers/changelog.py:67 -#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602 +#: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:602 msgid "There are no changesets yet" msgstr "Наборы изменений отсутствуют" #: kallithea/controllers/admin/permissions.py:64 #: kallithea/controllers/admin/permissions.py:68 #: kallithea/controllers/admin/permissions.py:72 -#: kallithea/controllers/changelog.py:137 +#: kallithea/controllers/changelog.py:136 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7 @@ -34,36 +34,36 @@ msgid "None" msgstr "Ничего" -#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189 +#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:189 msgid "(closed)" msgstr "(закрыто)" -#: kallithea/controllers/changeset.py:81 +#: kallithea/controllers/changeset.py:82 msgid "Show whitespace" msgstr "Отображать пробелы" -#: kallithea/controllers/changeset.py:88 -#: kallithea/controllers/changeset.py:95 +#: kallithea/controllers/changeset.py:89 +#: kallithea/controllers/changeset.py:96 #: kallithea/templates/files/diff_2way.html:55 msgid "Ignore whitespace" msgstr "Игнорировать пробелы" -#: kallithea/controllers/changeset.py:161 +#: kallithea/controllers/changeset.py:162 #, python-format msgid "Increase diff context to %(num)s lines" msgstr "Увеличить контекст до %(num)s строк" -#: kallithea/controllers/changeset.py:201 +#: kallithea/controllers/changeset.py:202 msgid "No permission to change status" msgstr "Недостаточно привилегий для изменения статуса" -#: kallithea/controllers/changeset.py:212 +#: kallithea/controllers/changeset.py:213 #, python-format msgid "Successfully deleted pull request %s" msgstr "Pull-запрос %s успешно удалён" -#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89 -#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700 +#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89 +#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697 msgid "Such revision does not exist for this repository" msgstr "Нет такой ревизии в этом репозитории" @@ -76,76 +76,77 @@ msgid "Cannot compare repositories of different types" msgstr "Невозможно сравнивать репозитории различных типов" -#: kallithea/controllers/compare.py:246 +#: kallithea/controllers/compare.py:247 msgid "Cannot show empty diff" msgstr "Отсутствуют изменения для отображения" -#: kallithea/controllers/compare.py:248 +#: kallithea/controllers/compare.py:249 msgid "No ancestor found for merge diff" msgstr "Не найдено предка для слияния" -#: kallithea/controllers/compare.py:252 +#: kallithea/controllers/compare.py:253 msgid "Multiple merge ancestors found for merge compare" msgstr "Найдено несколько предков для сравнения слияния" -#: kallithea/controllers/compare.py:268 +#: kallithea/controllers/compare.py:269 msgid "Cannot compare repositories without using common ancestor" msgstr "Невозможно сравнивать репозитории без общего предка" -#: kallithea/controllers/error.py:71 +#: kallithea/controllers/error.py:70 msgid "No response" msgstr "Нет ответа" -#: kallithea/controllers/error.py:72 +#: kallithea/controllers/error.py:71 msgid "Unknown error" msgstr "Неизвестная ошибка" -#: kallithea/controllers/error.py:85 +#: kallithea/controllers/error.py:84 msgid "" "The request could not be understood by the server due to malformed syntax." msgstr "Запрос не распознан сервером из-за неправильного синтаксиса." -#: kallithea/controllers/error.py:88 +#: kallithea/controllers/error.py:87 msgid "Unauthorized access to resource" msgstr "Несанкционированный доступ к ресурсу" -#: kallithea/controllers/error.py:90 +#: kallithea/controllers/error.py:89 msgid "You don't have permission to view this page" msgstr "У вас нет прав для просмотра этой страницы" -#: kallithea/controllers/error.py:92 +#: kallithea/controllers/error.py:91 msgid "The resource could not be found" msgstr "Ресурс не найден" -#: kallithea/controllers/error.py:94 +#: kallithea/controllers/error.py:93 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "" "Сервер не может выполнить запрос из-за неправильного условия в запросе." -#: kallithea/controllers/feed.py:63 +#: kallithea/controllers/feed.py:59 #, python-format msgid "%s committed on %s" msgstr "%s выполнил коммит в %s" -#: kallithea/controllers/feed.py:88 -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/controllers/feed.py:84 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/compare/compare_diff.html:95 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 msgid "Changeset was too big and was cut off..." msgstr "" -"Список изменений оказался слишком большим для отображения и был сокращён..." - -#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140 +"Список изменений оказался слишком большим для отображения и был " +"сокращён..." + +#: kallithea/controllers/feed.py:107 #, python-format msgid "%s %s feed" msgstr "Лента новостей %s %s" -#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142 +#: kallithea/controllers/feed.py:109 #, python-format msgid "Changes on %s repository" msgstr "Изменения в репозитории %s" @@ -163,94 +164,95 @@ msgid "%s at %s" msgstr "%s (%s)" -#: kallithea/controllers/files.py:296 +#: kallithea/controllers/files.py:295 msgid "You can only delete files with revision being a valid branch" -msgstr "Вы можете удалять файлы только в ревизии, являющейся корректной веткой" - -#: kallithea/controllers/files.py:307 +msgstr "" +"Вы можете удалять файлы только в ревизии, являющейся корректной веткой" + +#: kallithea/controllers/files.py:306 #, python-format msgid "Deleted file %s via Kallithea" msgstr "Файл %s удалён с помощью Kallithea" -#: kallithea/controllers/files.py:331 +#: kallithea/controllers/files.py:330 #, python-format msgid "Successfully deleted file %s" msgstr "Файл %s удалён" -#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394 -#: kallithea/controllers/files.py:469 +#: kallithea/controllers/files.py:334 kallithea/controllers/files.py:392 +#: kallithea/controllers/files.py:467 msgid "Error occurred during commit" msgstr "Во время коммита произошла ошибка" -#: kallithea/controllers/files.py:350 +#: kallithea/controllers/files.py:349 msgid "You can only edit files with revision being a valid branch" msgstr "" "Вы можете редактировать файлы только в ревизии, связанной с существующей " "веткой" -#: kallithea/controllers/files.py:364 +#: kallithea/controllers/files.py:363 #, python-format msgid "Edited file %s via Kallithea" msgstr "Файл %s отредактирован с помощью Kallithea" -#: kallithea/controllers/files.py:380 +#: kallithea/controllers/files.py:378 msgid "No changes" msgstr "Без изменений" -#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458 +#: kallithea/controllers/files.py:388 kallithea/controllers/files.py:456 #, python-format msgid "Successfully committed to %s" msgstr "Изменения применены в %s" -#: kallithea/controllers/files.py:409 +#: kallithea/controllers/files.py:407 msgid "Added file via Kallithea" msgstr "Файл добавлен с помощью Kallithea" -#: kallithea/controllers/files.py:430 +#: kallithea/controllers/files.py:428 msgid "No content" msgstr "Пусто" -#: kallithea/controllers/files.py:434 +#: kallithea/controllers/files.py:432 msgid "No filename" msgstr "Безымянный" -#: kallithea/controllers/files.py:461 +#: kallithea/controllers/files.py:459 msgid "Location must be relative path and must not contain .. in path" msgstr "" "Расположение должно быть относительным путем, и не должно содержать \".." "\" в пути" -#: kallithea/controllers/files.py:493 +#: kallithea/controllers/files.py:491 msgid "Downloads disabled" msgstr "Возможность скачивать отключена" -#: kallithea/controllers/files.py:504 +#: kallithea/controllers/files.py:502 #, python-format msgid "Unknown revision %s" msgstr "Неизвестная ревизия %s" -#: kallithea/controllers/files.py:506 +#: kallithea/controllers/files.py:504 msgid "Empty repository" msgstr "Пустой репозиторий" -#: kallithea/controllers/files.py:508 +#: kallithea/controllers/files.py:506 msgid "Unknown archive type" msgstr "Неизвестный тип архива" -#: kallithea/controllers/files.py:729 +#: kallithea/controllers/files.py:726 #: kallithea/templates/changeset/changeset_range.html:9 #: kallithea/templates/email_templates/pull_request.html:64 #: kallithea/templates/pullrequests/pullrequest.html:84 msgid "Changesets" msgstr "Набор изменений" -#: kallithea/controllers/files.py:730 -#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676 +#: kallithea/controllers/files.py:727 +#: kallithea/controllers/pullrequests.py:174 kallithea/model/scm.py:663 msgid "Branches" msgstr "Ветки" -#: kallithea/controllers/files.py:731 -#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687 +#: kallithea/controllers/files.py:728 +#: kallithea/controllers/pullrequests.py:175 kallithea/model/scm.py:674 msgid "Tags" msgstr "Метки" @@ -259,11 +261,11 @@ msgid "An error occurred during repository forking %s" msgstr "Произошла ошибка во время создания форка репозитория %s" -#: kallithea/controllers/home.py:79 +#: kallithea/controllers/home.py:77 msgid "Groups" msgstr "Группы" -#: kallithea/controllers/home.py:89 +#: kallithea/controllers/home.py:87 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90 #: kallithea/templates/admin/repos/repo_add.html:12 #: kallithea/templates/admin/repos/repo_add.html:16 @@ -275,195 +277,195 @@ msgid "Repositories" msgstr "Репозитории" -#: kallithea/controllers/home.py:122 +#: kallithea/controllers/home.py:119 #: 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:128 +#: kallithea/controllers/home.py:125 msgid "Closed Branches" msgstr "Закрытые ветки" -#: kallithea/controllers/home.py:134 +#: kallithea/controllers/home.py:131 msgid "Tag" msgstr "Тэги" -#: kallithea/controllers/home.py:140 +#: kallithea/controllers/home.py:137 msgid "Bookmark" msgstr "Закладки" -#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154 +#: kallithea/controllers/journal.py:146 kallithea/controllers/journal.py:157 #: kallithea/templates/journal/public_journal.html:4 #: kallithea/templates/journal/public_journal.html:18 msgid "Public Journal" msgstr "Публичный журнал" -#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158 +#: kallithea/controllers/journal.py:150 kallithea/controllers/journal.py:161 #: kallithea/templates/base/base.html:290 #: kallithea/templates/journal/journal.html:5 #: kallithea/templates/journal/journal.html:13 msgid "Journal" msgstr "Журнал" -#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185 +#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184 msgid "Bad captcha" msgstr "Неверная капча" -#: kallithea/controllers/login.py:146 +#: kallithea/controllers/login.py:145 #, python-format msgid "You have successfully registered with %s" msgstr "Регистрация в %s прошла успешно" -#: kallithea/controllers/login.py:190 +#: kallithea/controllers/login.py:189 msgid "A password reset confirmation code has been sent" msgstr "Код для сброса пароля отправлена" -#: kallithea/controllers/login.py:239 +#: kallithea/controllers/login.py:236 msgid "Invalid password reset token" msgstr "Неверный код сброса пароля" #: kallithea/controllers/admin/my_account.py:157 -#: kallithea/controllers/login.py:244 +#: kallithea/controllers/login.py:241 msgid "Successfully updated password" msgstr "Пароль обновлён" -#: kallithea/controllers/pullrequests.py:68 +#: kallithea/controllers/pullrequests.py:67 #, python-format msgid "Invalid reviewer \"%s\" specified" msgstr "Некорректно задан ревьювер «%s»" -#: kallithea/controllers/pullrequests.py:131 +#: kallithea/controllers/pullrequests.py:123 #, python-format msgid "%s (closed)" msgstr "%s (закрыта)" -#: kallithea/controllers/pullrequests.py:158 +#: kallithea/controllers/pullrequests.py:150 #: kallithea/templates/changeset/changeset.html:12 msgid "Changeset" msgstr "Изменения" -#: kallithea/controllers/pullrequests.py:179 +#: kallithea/controllers/pullrequests.py:171 msgid "Special" msgstr "Специальный" -#: kallithea/controllers/pullrequests.py:180 +#: kallithea/controllers/pullrequests.py:172 msgid "Peer branches" msgstr "Ветви участника" -#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682 +#: kallithea/controllers/pullrequests.py:173 kallithea/model/scm.py:669 msgid "Bookmarks" msgstr "Закладки" -#: kallithea/controllers/pullrequests.py:318 +#: kallithea/controllers/pullrequests.py:315 #, python-format msgid "Error creating pull request: %s" msgstr "Ошибка при создании pull-запроса: %s" -#: kallithea/controllers/pullrequests.py:345 -#: kallithea/controllers/pullrequests.py:368 +#: kallithea/controllers/pullrequests.py:342 +#: kallithea/controllers/pullrequests.py:365 msgid "Error occurred while creating pull request" msgstr "Произошла ошибка при создании pull-запроса" -#: kallithea/controllers/pullrequests.py:350 +#: kallithea/controllers/pullrequests.py:347 msgid "Successfully opened new pull request" msgstr "Pull-запрос успешно открыт" -#: kallithea/controllers/pullrequests.py:373 +#: kallithea/controllers/pullrequests.py:370 msgid "New pull request iteration created" msgstr "Создана новая итерация pull-запросов" -#: kallithea/controllers/pullrequests.py:401 +#: kallithea/controllers/pullrequests.py:398 #, python-format msgid "Meanwhile, the following reviewers have been added: %s" msgstr "В то же время, добавлены следующие ревьюверы: %s" -#: kallithea/controllers/pullrequests.py:405 +#: kallithea/controllers/pullrequests.py:402 #, python-format msgid "Meanwhile, the following reviewers have been removed: %s" msgstr "В то же время, удалены следующие ревьюверы: %s" -#: kallithea/controllers/pullrequests.py:421 -#: kallithea/model/pull_request.py:232 +#: kallithea/controllers/pullrequests.py:418 +#: kallithea/model/pull_request.py:230 msgid "No description" msgstr "Нет описания" -#: kallithea/controllers/pullrequests.py:430 +#: kallithea/controllers/pullrequests.py:427 msgid "Pull request updated" msgstr "Pull-запрос обновлён" -#: kallithea/controllers/pullrequests.py:443 +#: kallithea/controllers/pullrequests.py:440 msgid "Successfully deleted pull request" msgstr "Pull-запрос успешно удалён" -#: kallithea/controllers/pullrequests.py:479 +#: kallithea/controllers/pullrequests.py:476 #, python-format msgid "Revision %s not found in %s" msgstr "Ревизия %s не найдена в %s" -#: kallithea/controllers/pullrequests.py:506 +#: kallithea/controllers/pullrequests.py:504 #, python-format msgid "Error: changesets not found when displaying pull request from %s." msgstr "Ошибка: не найдены изменения при отображении pull-запроса от %s." -#: kallithea/controllers/pullrequests.py:520 +#: kallithea/controllers/pullrequests.py:518 #, python-format msgid "This pull request has already been merged to %s." msgstr "Этот pull-запрос уже принят на ветку %s." -#: kallithea/controllers/pullrequests.py:522 +#: kallithea/controllers/pullrequests.py:520 msgid "This pull request has been closed and can not be updated." msgstr "Этот pull-запрос был закрыт и не может быть обновлён." -#: kallithea/controllers/pullrequests.py:546 +#: kallithea/controllers/pullrequests.py:539 #, python-format msgid "The following additional changes are available on %s:" msgstr "Следующие дополнительные изменения доступны на %s:" -#: kallithea/controllers/pullrequests.py:548 -#: kallithea/controllers/pullrequests.py:552 +#: kallithea/controllers/pullrequests.py:541 +#: kallithea/controllers/pullrequests.py:545 msgid "No additional changesets found for iterating on this pull request." msgstr "Нет дополнительных изменений для итерации в этом pull-запросе." -#: kallithea/controllers/pullrequests.py:560 +#: kallithea/controllers/pullrequests.py:553 #, python-format msgid "Note: Branch %s has another head: %s." msgstr "Внимание: Ветка %s имеет ещё одну верхушку: %s." -#: kallithea/controllers/pullrequests.py:567 +#: kallithea/controllers/pullrequests.py:560 msgid "Git pull requests don't support iterating yet." msgstr "Pull-запросы git пока не поддерживают итерации." -#: kallithea/controllers/pullrequests.py:569 +#: kallithea/controllers/pullrequests.py:562 #, python-format msgid "" "Error: some changesets not found when displaying pull request from %s." msgstr "" "Ошибка: не найдены некоторые изменения при отображении pull-запроса от %s." -#: kallithea/controllers/pullrequests.py:593 +#: kallithea/controllers/pullrequests.py:586 msgid "The diff can't be shown - the PR revisions could not be found." msgstr "Невозможно отобразить различия — не найдены ревизии PR." +#: kallithea/controllers/search.py:132 +msgid "Invalid search query. Try quoting it." +msgstr "Недопустимый поисковый запрос. Попробуйте заключить его в кавычки." + #: kallithea/controllers/search.py:136 -msgid "Invalid search query. Try quoting it." -msgstr "Недопустимый поисковый запрос. Попробуйте заключить его в кавычки." - -#: kallithea/controllers/search.py:140 msgid "The server has no search index." msgstr "На сервере отсутствует поисковый индекс." -#: kallithea/controllers/search.py:143 +#: kallithea/controllers/search.py:139 msgid "An error occurred during search operation." msgstr "Произошла ошибка при выполнении этого поиска." -#: kallithea/controllers/summary.py:168 -#: kallithea/templates/summary/summary.html:412 +#: kallithea/controllers/summary.py:169 +#: kallithea/templates/summary/summary.html:410 msgid "No data ready yet" msgstr "Нет данных" -#: kallithea/controllers/summary.py:171 +#: kallithea/controllers/summary.py:172 #: kallithea/templates/summary/summary.html:97 msgid "Statistics are disabled for this repository" msgstr "Статистические данные отключены для этого репозитария" @@ -476,80 +478,80 @@ msgid "error occurred during update of auth settings" msgstr "произошла ошибка при обновлении настроек авторизации" -#: kallithea/controllers/admin/defaults.py:75 +#: kallithea/controllers/admin/defaults.py:74 msgid "Default settings updated successfully" msgstr "Настройки по умолчанию успешно обновлены" -#: kallithea/controllers/admin/defaults.py:90 +#: kallithea/controllers/admin/defaults.py:89 msgid "Error occurred during update of defaults" msgstr "Произошла ошибка при обновлении стандартных настроек" #: kallithea/controllers/admin/gists.py:59 #: kallithea/controllers/admin/my_account.py:232 -#: kallithea/controllers/admin/users.py:248 +#: kallithea/controllers/admin/users.py:246 msgid "Forever" msgstr "Не ограничено" #: kallithea/controllers/admin/gists.py:60 #: kallithea/controllers/admin/my_account.py:233 -#: kallithea/controllers/admin/users.py:249 +#: kallithea/controllers/admin/users.py:247 msgid "5 minutes" msgstr "5 минут" #: kallithea/controllers/admin/gists.py:61 #: kallithea/controllers/admin/my_account.py:234 -#: kallithea/controllers/admin/users.py:250 +#: kallithea/controllers/admin/users.py:248 msgid "1 hour" msgstr "1 час" #: kallithea/controllers/admin/gists.py:62 #: kallithea/controllers/admin/my_account.py:235 -#: kallithea/controllers/admin/users.py:251 +#: kallithea/controllers/admin/users.py:249 msgid "1 day" msgstr "1 день" #: kallithea/controllers/admin/gists.py:63 #: kallithea/controllers/admin/my_account.py:236 -#: kallithea/controllers/admin/users.py:252 +#: kallithea/controllers/admin/users.py:250 msgid "1 month" msgstr "1 месяц" #: kallithea/controllers/admin/gists.py:67 #: kallithea/controllers/admin/my_account.py:238 -#: kallithea/controllers/admin/users.py:254 +#: kallithea/controllers/admin/users.py:252 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65 #: kallithea/templates/admin/users/user_edit_api_keys.html:65 msgid "Lifetime" msgstr "Срок" -#: kallithea/controllers/admin/gists.py:142 +#: kallithea/controllers/admin/gists.py:148 msgid "Error occurred during gist creation" msgstr "Произошла ошибка во время создания gist-записи" -#: kallithea/controllers/admin/gists.py:158 +#: kallithea/controllers/admin/gists.py:164 #, python-format msgid "Deleted gist %s" msgstr "Gist-запись %s удалена" -#: kallithea/controllers/admin/gists.py:198 +#: kallithea/controllers/admin/gists.py:207 msgid "Unmodified" msgstr "Неизменный" -#: kallithea/controllers/admin/gists.py:228 +#: kallithea/controllers/admin/gists.py:237 msgid "Successfully updated gist content" msgstr "Содержимое gist-записи обновлено" -#: kallithea/controllers/admin/gists.py:233 +#: kallithea/controllers/admin/gists.py:242 msgid "Successfully updated gist data" msgstr "Данные gist-записи обновлены" -#: kallithea/controllers/admin/gists.py:236 +#: kallithea/controllers/admin/gists.py:245 #, python-format msgid "Error occurred during update of gist %s" msgstr "Произошла ошибка при обновлении gist-записи %s" -#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211 -#: kallithea/model/user.py:232 +#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209 +#: kallithea/model/user.py:230 msgid "You can't edit this user since it's crucial for entire application" msgstr "" "Вы не можете изменить данные этого пользователя, поскольку он важен для " @@ -560,7 +562,7 @@ msgstr "Ваша учетная запись успешно обновлена" #: kallithea/controllers/admin/my_account.py:134 -#: kallithea/controllers/admin/users.py:181 +#: kallithea/controllers/admin/users.py:179 #, python-format msgid "Error occurred during update of user %s" msgstr "Произошла ошибка при обновлении пользователя %s" @@ -570,44 +572,44 @@ msgstr "Ошибка при обновлении пароля" #: kallithea/controllers/admin/my_account.py:209 -#: kallithea/controllers/admin/users.py:367 +#: kallithea/controllers/admin/users.py:365 #, python-format msgid "Added email %s to user" msgstr "Пользователю добавлен e-mail %s" #: kallithea/controllers/admin/my_account.py:215 -#: kallithea/controllers/admin/users.py:373 +#: kallithea/controllers/admin/users.py:371 msgid "An error occurred during email saving" msgstr "Произошла ошибка при сохранении e-mail" #: kallithea/controllers/admin/my_account.py:224 -#: kallithea/controllers/admin/users.py:383 +#: kallithea/controllers/admin/users.py:381 msgid "Removed email from user" msgstr "E-mail пользователя удалён" #: kallithea/controllers/admin/my_account.py:248 -#: kallithea/controllers/admin/users.py:271 +#: kallithea/controllers/admin/users.py:269 msgid "API key successfully created" msgstr "API-ключ успешно создан" #: kallithea/controllers/admin/my_account.py:257 -#: kallithea/controllers/admin/users.py:281 +#: kallithea/controllers/admin/users.py:279 msgid "API key successfully reset" msgstr "API-ключ успешно сброшен" #: kallithea/controllers/admin/my_account.py:261 -#: kallithea/controllers/admin/users.py:285 +#: kallithea/controllers/admin/users.py:283 msgid "API key successfully deleted" msgstr "API-ключ успешно удалён" #: kallithea/controllers/admin/my_account.py:281 -#: kallithea/controllers/admin/users.py:456 +#: kallithea/controllers/admin/users.py:454 #, python-format msgid "SSH key %s successfully added" msgstr "Ключ SSH %s успешно добавлен" #: kallithea/controllers/admin/my_account.py:293 -#: kallithea/controllers/admin/users.py:470 +#: kallithea/controllers/admin/users.py:468 msgid "SSH key successfully deleted" msgstr "Ключ SSH успешно удалён" @@ -683,11 +685,11 @@ msgid "Allowed with automatic account activation" msgstr "Разрешена, с автоматической активацией учётной записи" -#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673 +#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670 msgid "Manual activation of external account" msgstr "Ручная активация внешней учетной записи" -#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674 +#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671 msgid "Automatic activation of external account" msgstr "Автоматическая активация внешней учетной записи" @@ -709,59 +711,59 @@ msgid "Error occurred during update of permissions" msgstr "Произошла ошибка во время обновления привилегий" -#: kallithea/controllers/admin/repo_groups.py:172 +#: kallithea/controllers/admin/repo_groups.py:167 #, python-format msgid "Error occurred during creation of repository group %s" msgstr "Произошла ошибка при создании группы репозиториев %s" -#: kallithea/controllers/admin/repo_groups.py:177 +#: kallithea/controllers/admin/repo_groups.py:174 #, python-format msgid "Created repository group %s" msgstr "Создана новая группа репозиториев %s" -#: kallithea/controllers/admin/repo_groups.py:224 +#: kallithea/controllers/admin/repo_groups.py:221 #, python-format msgid "Updated repository group %s" msgstr "Группа репозиториев %s обновлена" -#: kallithea/controllers/admin/repo_groups.py:240 +#: kallithea/controllers/admin/repo_groups.py:237 #, python-format msgid "Error occurred during update of repository group %s" msgstr "Произошла ошибка при обновлении группы репозиториев %s" -#: kallithea/controllers/admin/repo_groups.py:250 +#: kallithea/controllers/admin/repo_groups.py:247 #, python-format msgid "This group contains %s repositories and cannot be deleted" msgstr "Данная группа содержит %s репозитариев и не может быть удалена" -#: kallithea/controllers/admin/repo_groups.py:257 +#: kallithea/controllers/admin/repo_groups.py:254 #, python-format msgid "This group contains %s subgroups and cannot be deleted" msgstr "Группа содержит в себе %s подгрупп и не может быть удалён" -#: kallithea/controllers/admin/repo_groups.py:263 +#: kallithea/controllers/admin/repo_groups.py:260 #, python-format msgid "Removed repository group %s" msgstr "Группа репозиториев %s удалена" -#: kallithea/controllers/admin/repo_groups.py:268 +#: kallithea/controllers/admin/repo_groups.py:265 #, python-format msgid "Error occurred during deletion of repository group %s" msgstr "Произошла ошибка при удалении группы репозиториев %s" -#: kallithea/controllers/admin/repo_groups.py:352 -#: kallithea/controllers/admin/repo_groups.py:382 -#: kallithea/controllers/admin/user_groups.py:294 +#: kallithea/controllers/admin/repo_groups.py:349 +#: kallithea/controllers/admin/repo_groups.py:379 +#: kallithea/controllers/admin/user_groups.py:292 msgid "Cannot revoke permission for yourself as admin" msgstr "Администратор не может отозвать свои привелегии" -#: kallithea/controllers/admin/repo_groups.py:367 +#: kallithea/controllers/admin/repo_groups.py:364 msgid "Repository group permissions updated" msgstr "Привилегии группы репозиториев обновлены" -#: kallithea/controllers/admin/repo_groups.py:399 +#: kallithea/controllers/admin/repo_groups.py:396 #: kallithea/controllers/admin/repos.py:358 -#: kallithea/controllers/admin/user_groups.py:306 +#: kallithea/controllers/admin/user_groups.py:304 msgid "An error occurred during revoking of permission" msgstr "Произошла ошибка при отзыве привелегии" @@ -887,7 +889,7 @@ msgid "Updated VCS settings" msgstr "Обновлены настройки VCS" -#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237 +#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238 msgid "" "Unable to activate hgsubversion support. The \"hgsubversion\" library is " "missing" @@ -956,98 +958,98 @@ msgid "Whoosh reindex task scheduled" msgstr "Переиндексация базы Whoosh успешно запланирована" -#: kallithea/controllers/admin/user_groups.py:138 +#: kallithea/controllers/admin/user_groups.py:136 #, python-format msgid "Created user group %s" msgstr "Создана группа пользователей %s" -#: kallithea/controllers/admin/user_groups.py:151 +#: kallithea/controllers/admin/user_groups.py:149 #, python-format msgid "Error occurred during creation of user group %s" msgstr "Произошла ошибка при создании группы пользователей %s" -#: kallithea/controllers/admin/user_groups.py:179 +#: kallithea/controllers/admin/user_groups.py:177 #, python-format msgid "Updated user group %s" msgstr "Группа пользователей %s обновлена" -#: kallithea/controllers/admin/user_groups.py:201 +#: kallithea/controllers/admin/user_groups.py:199 #, python-format msgid "Error occurred during update of user group %s" msgstr "Произошла ошибка при обновлении группы пользователей %s" -#: kallithea/controllers/admin/user_groups.py:212 +#: kallithea/controllers/admin/user_groups.py:210 msgid "Successfully deleted user group" msgstr "Группа пользователей успешно удалена" -#: kallithea/controllers/admin/user_groups.py:217 +#: kallithea/controllers/admin/user_groups.py:215 msgid "An error occurred during deletion of user group" msgstr "Произошла ошибка при удалении группы пользователей" -#: kallithea/controllers/admin/user_groups.py:273 +#: kallithea/controllers/admin/user_groups.py:271 msgid "Target group cannot be the same" msgstr "Целевая группа не может быть такой же" -#: kallithea/controllers/admin/user_groups.py:279 +#: kallithea/controllers/admin/user_groups.py:277 msgid "User group permissions updated" msgstr "Привилегии группы пользователей обновлены" -#: kallithea/controllers/admin/user_groups.py:388 -#: kallithea/controllers/admin/users.py:338 +#: kallithea/controllers/admin/user_groups.py:386 +#: kallithea/controllers/admin/users.py:336 msgid "Updated permissions" msgstr "Обновлены привилегии" -#: kallithea/controllers/admin/user_groups.py:392 -#: kallithea/controllers/admin/users.py:342 +#: kallithea/controllers/admin/user_groups.py:390 +#: kallithea/controllers/admin/users.py:340 msgid "An error occurred during permissions saving" msgstr "Произошла ошибка при сохранении привилегий" -#: kallithea/controllers/admin/users.py:123 +#: kallithea/controllers/admin/users.py:121 #, python-format msgid "Created user %s" msgstr "Пользователь %s создан" -#: kallithea/controllers/admin/users.py:138 +#: kallithea/controllers/admin/users.py:136 #, python-format msgid "Error occurred during creation of user %s" msgstr "Произошла ошибка при создании пользователя %s" -#: kallithea/controllers/admin/users.py:162 +#: kallithea/controllers/admin/users.py:160 msgid "User updated successfully" msgstr "Пользователь успешно обновлён" -#: kallithea/controllers/admin/users.py:190 +#: kallithea/controllers/admin/users.py:188 msgid "Successfully deleted user" msgstr "Пользователь успешно удалён" -#: kallithea/controllers/admin/users.py:195 +#: kallithea/controllers/admin/users.py:193 msgid "An error occurred during deletion of user" msgstr "Произошла ошибка при удалении пользователя" -#: kallithea/controllers/admin/users.py:203 +#: kallithea/controllers/admin/users.py:201 msgid "The default user cannot be edited" msgstr "Нельзя редактировать пользователя по умолчанию" -#: kallithea/controllers/admin/users.py:409 +#: kallithea/controllers/admin/users.py:407 #, python-format msgid "Added IP address %s to user whitelist" msgstr "Добавлен IP %s в белый список пользователя" -#: kallithea/controllers/admin/users.py:415 +#: kallithea/controllers/admin/users.py:413 msgid "An error occurred while adding IP address" msgstr "Произошла ошибка при сохранении IP" -#: kallithea/controllers/admin/users.py:427 +#: kallithea/controllers/admin/users.py:425 msgid "Removed IP address from user whitelist" msgstr "Удален IP %s из белого списка пользователя" -#: kallithea/lib/auth.py:684 +#: kallithea/lib/auth.py:668 msgid "You need to be a registered user to perform this action" msgstr "" "Вы должны быть зарегистрированным пользователем, чтобы выполнить это " "действие" -#: kallithea/lib/auth.py:712 +#: kallithea/lib/auth.py:696 msgid "You need to be signed in to view this page" msgstr "Страница доступна только авторизованным пользователям" @@ -1080,170 +1082,170 @@ "Набор изменения оказался слишком большими и был урезан, используйте меню " "сравнения для показа результата сравнения" -#: kallithea/lib/diffs.py:224 +#: kallithea/lib/diffs.py:223 msgid "No changes detected" msgstr "Изменений не обнаружено" -#: kallithea/lib/helpers.py:653 +#: kallithea/lib/helpers.py:646 #, python-format msgid "Deleted branch: %s" msgstr "Удалена ветка: %s" -#: kallithea/lib/helpers.py:655 +#: kallithea/lib/helpers.py:648 #, python-format msgid "Created tag: %s" msgstr "Создан тег: %s" -#: kallithea/lib/helpers.py:666 +#: kallithea/lib/helpers.py:659 #, python-format msgid "Changeset %s not found" msgstr "Набор изменений %s не найден" -#: kallithea/lib/helpers.py:715 +#: kallithea/lib/helpers.py:708 #, python-format msgid "Show all combined changesets %s->%s" msgstr "Показать отличия вместе %s->%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "Сравнить вид" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "и" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "на %s больше" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "версии" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "Имя форка %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "Pull-запрос %s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "[удален] репозиторий" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "[создан] репозиторий" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[создан] репозиторий в качестве форка" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "[создан форк] репозитория" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "[обновлён] репозиторий" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "[загружен] архив из репозитория" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "[удален] репозиторий" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "[создан] пользователь" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "[обновлён] пользователь" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "[создана] группа пользователей" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "[обновлена] группа пользователей" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "[комментарий] к ревизии в репозитории" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "[прокомментировано] в pull-запросе для" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "[закрыт] pull-запрос для" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[отправлено] в" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "[внесены изменения с помощью Kallithea] в репозитории" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "[внесены изменения из удалённого репозитория] в репозиторий" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[внесены изменения] из" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "[подписка] на репозиторий" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "[отписка] от репозитория" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " и на %s больше" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Нет файлов" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "новый файл" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "изменён" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "удалён" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "переименован" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1254,35 +1256,42 @@ "переименован из файловой системы. Пожалуйста, перезапустите приложение " "для сканирования репозиториев" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "Отсутствует ключ SSH" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "Некорректный ключ SSH — должен присутствовать тип ключа и код base64" - #: kallithea/lib/ssh.py:79 +#, fuzzy +#| msgid "" +#| "Incorrect SSH key - it must have both a key type and a base64 part" +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" +"Некорректный ключ SSH — должен присутствовать тип ключа и код base64" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" -msgstr "Некорректный ключ SSH — он должен начинаться с 'ssh-(rsa|dss|ed25519)'" - -#: kallithea/lib/ssh.py:82 +msgstr "" +"Некорректный ключ SSH — он должен начинаться с 'ssh-(rsa|dss|ed25519)'" + +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" "Некорректный ключ SSH — присутствуют некорректные символы в коде base64 %r" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "Некорректный ключ SSH — ошибка декодирования кода base64 %r" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "Некорректный ключ SSH — код base64 соответствует не %r, а %r" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" @@ -1290,7 +1299,7 @@ msgstr[1] "%d года" msgstr[2] "%d лет" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" @@ -1298,7 +1307,7 @@ msgstr[1] "%d месяца" msgstr[2] "%d месяцев" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" @@ -1306,7 +1315,7 @@ msgstr[1] "%d дня" msgstr[2] "%d дней" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" @@ -1314,7 +1323,7 @@ msgstr[1] "%d часа" msgstr[2] "%d часов" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" @@ -1322,7 +1331,7 @@ msgstr[1] "%d минуты" msgstr[2] "%d минут" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" @@ -1330,27 +1339,27 @@ msgstr[1] "%d секунды" msgstr[2] "%d секунд" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "в %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "%s назад" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "в %s и %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s и %s назад" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "только что" @@ -1359,151 +1368,155 @@ msgid "on line %s" msgstr "на строке %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Упоминание]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "верхний уровень" -#: kallithea/model/db.py:1637 +#: kallithea/model/db.py:1634 msgid "Kallithea Administrator" msgstr "Администратор Kallithea" -#: kallithea/model/db.py:1639 +#: kallithea/model/db.py:1636 msgid "Default user has no access to new repositories" msgstr "" "Неавторизованные пользователи не имеют прав доступа к новым репозиториям" -#: kallithea/model/db.py:1640 +#: kallithea/model/db.py:1637 msgid "Default user has read access to new repositories" msgstr "Неавторизованные пользователи имеют право чтения новых репозиториев" -#: kallithea/model/db.py:1641 +#: kallithea/model/db.py:1638 msgid "Default user has write access to new repositories" msgstr "" "Неавторизованные пользователи имеют право записи в новые репозитории" -#: kallithea/model/db.py:1642 +#: kallithea/model/db.py:1639 msgid "Default user has admin access to new repositories" msgstr "" -"Неавторизованные пользователи имеют права администратора к новым репозиториям" - -#: kallithea/model/db.py:1644 +"Неавторизованные пользователи имеют права администратора к новым " +"репозиториям" + +#: kallithea/model/db.py:1641 msgid "Default user has no access to new repository groups" msgstr "" "Неавторизованные пользователи не имеют прав доступа к новым группам " "репозиториев" -#: kallithea/model/db.py:1645 +#: kallithea/model/db.py:1642 msgid "Default user has read access to new repository groups" msgstr "" -"Неавторизованные пользователи имеют право чтения в новых группах репозиториев" - -#: kallithea/model/db.py:1646 +"Неавторизованные пользователи имеют право чтения в новых группах " +"репозиториев" + +#: kallithea/model/db.py:1643 msgid "Default user has write access to new repository groups" msgstr "" -"Неавторизованные пользователи имеют право записи в новых группах репозиториев" - -#: kallithea/model/db.py:1647 +"Неавторизованные пользователи имеют право записи в новых группах " +"репозиториев" + +#: kallithea/model/db.py:1644 msgid "Default user has admin access to new repository groups" msgstr "" "Неавторизованные пользователи имеют права администратора к новым групппам " "репозиториев" -#: kallithea/model/db.py:1649 +#: kallithea/model/db.py:1646 msgid "Default user has no access to new user groups" msgstr "" "Неавторизованные пользователи не имеют прав доступа к новым группам " "пользователей" -#: kallithea/model/db.py:1650 +#: kallithea/model/db.py:1647 msgid "Default user has read access to new user groups" msgstr "" "Неавторизованные пользователи имеют право чтения в новых группах " "пользователей" -#: kallithea/model/db.py:1651 +#: kallithea/model/db.py:1648 msgid "Default user has write access to new user groups" msgstr "" "Неавторизованные пользователи имеют право записи в новых группах " "пользователей" -#: kallithea/model/db.py:1652 +#: kallithea/model/db.py:1649 msgid "Default user has admin access to new user groups" msgstr "" "Неавторизованные пользователи имеют права администратора к новым групппам " "пользователей" -#: kallithea/model/db.py:1654 +#: kallithea/model/db.py:1651 msgid "Only admins can create repository groups" msgstr "Только администраторы могут создавать группы репозиториев" -#: kallithea/model/db.py:1655 +#: kallithea/model/db.py:1652 msgid "Non-admins can create repository groups" msgstr "Группы репозиториев могут создаваться любыми пользователями" -#: kallithea/model/db.py:1657 +#: kallithea/model/db.py:1654 msgid "Only admins can create user groups" msgstr "Группы пользователей могут создаваться только администраторами" -#: kallithea/model/db.py:1658 +#: kallithea/model/db.py:1655 msgid "Non-admins can create user groups" msgstr "Группы пользователей могут создаваться любыми пользователями" -#: kallithea/model/db.py:1660 +#: kallithea/model/db.py:1657 msgid "Only admins can create top level repositories" msgstr "Только администраторы могут создавать репозитории верхнего уровня" -#: kallithea/model/db.py:1661 +#: kallithea/model/db.py:1658 msgid "Non-admins can create top level repositories" msgstr "Любой пользователь может создавать репозитории верхнего уровня" -#: kallithea/model/db.py:1663 +#: kallithea/model/db.py:1660 msgid "" "Repository creation enabled with write permission to a repository group" -msgstr "Создание репозиториев доступно с правом на запись в группу репозиториев" - -#: kallithea/model/db.py:1664 +msgstr "" +"Создание репозиториев доступно с правом на запись в группу репозиториев" + +#: kallithea/model/db.py:1661 msgid "" "Repository creation disabled with write permission to a repository group" msgstr "" "Создание репозиториев недоступно с правом на запись в группу репозиториев" -#: kallithea/model/db.py:1666 +#: kallithea/model/db.py:1663 msgid "Only admins can fork repositories" msgstr "Форки репозиториев могут создаваться только администраторами" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 msgid "Non-admins can fork repositories" msgstr "Форки репозиториев могут создаваться любыми пользователями" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "Регистрация отключена" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "Регистрация пользователя с ручной активацией учётной записи" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "Регистрация пользователя с автоматической активацией" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 msgid "Not reviewed" msgstr "Не проверено" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 msgid "Under review" msgstr "На проверке" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 msgid "Not approved" msgstr "Не одобрено" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "Одобрено" @@ -1529,7 +1542,7 @@ msgid "Name must not contain only digits" msgstr "Имя не может состоять только из цифр" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " @@ -1538,12 +1551,12 @@ "[Комментарий] к набору изменений %(short_id)s «%(message_short)s» " "репозитория %(repo_name)s в %(branch)s" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "Новый пользователь \"%(new_username)s\" зарегистрирован" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " @@ -1552,104 +1565,106 @@ "[Ревью] к PR %(pr_nice_id)s «%(pr_title_short)s» из %(pr_source_branch)s " "репозитория %(repo_name)s от %(pr_owner_username)s" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -"[Комментарий] к PR %(pr_nice_id)s «%(pr_title_short)s» из %(pr_source_branch)" -"s репозитория %(repo_name)s от %(pr_owner_username)s" - -#: kallithea/model/notification.py:183 +"[Комментарий] к PR %(pr_nice_id)s «%(pr_title_short)s» из " +"%(pr_source_branch)s репозитория %(repo_name)s от %(pr_owner_username)s" + +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "Закрыт" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" "%(user)s просит вас рассмотреть pull-запрос %(pr_nice_id)s: %(pr_title)s" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "Невозможно создать пустой pull-запрос" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -"Невозможно создать pull-запрос — обнаружено перекрёстное слияние. Попробуйте " -"слить более позднюю ревизию %s с %s" - -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +"Невозможно создать pull-запрос — обнаружено перекрёстное слияние. " +"Попробуйте слить более позднюю ревизию %s с %s" + +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "Недостаточно привилегий для создания pull-запроса" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "Отсутствующие ревизии относительно предыдущей итерации:" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "Новые наборы изменений в %s %s относительно предыдущей итерации:" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "Предок не изменился — разница с момента последней итерации:" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." -msgstr "Эта итерация основана на другой ревизии %s, простой diff невозможен." - -#: kallithea/model/pull_request.py:362 +msgstr "" +"Эта итерация основана на другой ревизии %s, простой diff невозможен." + +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "Нет изменений на %s %s относительно предыдущей итерации." -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "Закрыто. Следующая итерация: %s." -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "последняя версия" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "Ошибка ключа SSH %r: %s" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "Ключ SSH %s уже используется пользователем %s" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" +#: kallithea/model/ssh_key.py:88 +#, fuzzy, python-format +#| msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Ключ SSH %r не найден" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "Регистрация нового пользователя" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -"Вы не можете удалить этого пользователя, поскольку это критично для работы " -"всего приложения" - -#: kallithea/model/user.py:255 +"Вы не можете удалить этого пользователя, поскольку это критично для " +"работы всего приложения" + +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " @@ -1658,7 +1673,7 @@ "Пользователь \"%s\" всё ещё является владельцем %s репозиториев и поэтому " "не может быть удалён. Смените владельца или удалите эти репозитории: %s" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " @@ -1668,7 +1683,7 @@ "поэтому не может быть удалён. Смените владельца или удалите данные " "группы: %s" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " @@ -1678,15 +1693,15 @@ "поэтому не может быть удалён. Смените владельца или удалите данные " "группы: %s" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "Ссылка сброса пароля" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "Уведомление о сбросе пароля" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -1712,9 +1727,9 @@ "Username may only contain alphanumeric characters underscores, periods or " "dashes and must begin with an alphanumeric character or underscore" msgstr "" -"Имя пользователя может содержать только буквы, цифры, символы подчеркивания, " -"точки и тире, а также должно начинаться с буквы, цифры или с символа " -"подчеркивания" +"Имя пользователя может содержать только буквы, цифры, символы " +"подчеркивания, точки и тире, а также должно начинаться с буквы, цифры или " +"с символа подчеркивания" #: kallithea/model/validators.py:103 msgid "The input is not valid" @@ -1801,8 +1816,8 @@ "Invalid repository URL. It must be a valid http, https, ssh, svn+http or " "svn+https URL" msgstr "" -"Недопустимый URL репозитория. Требуется корректный http, https, ssh, svn+" -"http или svn+https URL" +"Недопустимый URL репозитория. Требуется корректный http, https, ssh, svn" +"+http или svn+https URL" #: kallithea/model/validators.py:430 msgid "Fork has to be the same type as parent" @@ -2039,8 +2054,8 @@ "A password reset link will be sent to the specified email address if it " "is registered in the system." msgstr "" -"Ссылка для сброса пароля была отправлена на соответствующий e-mail, если он " -"был зарегистрирован в системе." +"Ссылка для сброса пароля была отправлена на соответствующий e-mail, если " +"он был зарегистрирован в системе." #: kallithea/templates/password_reset_confirmation.html:23 #, python-format @@ -2052,8 +2067,8 @@ "Note that you must use the same browser session for this as the one used " "to request the password reset." msgstr "" -"Обратите внимание, что вы должны оставаться в пределах этой сессии браузера, " -"поскольку в ней был запрошен сброс пароля." +"Обратите внимание, что вы должны оставаться в пределах этой сессии " +"браузера, поскольку в ней был запрошен сброс пароля." #: kallithea/templates/password_reset_confirmation.html:29 msgid "Code you received in the email" @@ -2113,8 +2128,8 @@ #: kallithea/templates/register.html:85 msgid "Registered accounts are ready to use and need no further action." msgstr "" -"Зарегистрированные аккаунты готовы к использованию и не требуют дальнейших " -"действий." +"Зарегистрированные аккаунты готовы к использованию и не требуют " +"дальнейших действий." #: kallithea/templates/register.html:87 msgid "Please wait for an administrator to activate your account." @@ -2282,8 +2297,8 @@ "Gist was updated since you started editing. Copy your changes and click " "%(here)s to reload new version." msgstr "" -"Gist был изменён с момента начала редактирования. Скопируйте свои правки и " -"нажмите %(here)s для загрузки новой версии." +"Gist был изменён с момента начала редактирования. Скопируйте свои правки " +"и нажмите %(here)s для загрузки новой версии." #: kallithea/templates/admin/gists/edit.html:36 msgid "here" @@ -2401,7 +2416,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -2764,8 +2779,8 @@ "Allow access to Kallithea without needing to log in. Anonymous users use " "%s user permissions." msgstr "" -"Разрешить доступ к Kallithea без авторизации. Анонимные пользователи будут " -"использовать права доступа пользователя %s." +"Разрешить доступ к Kallithea без авторизации. Анонимные пользователи " +"будут использовать права доступа пользователя %s." #: kallithea/templates/admin/permissions/permissions_globals.html:19 msgid "" @@ -2823,8 +2838,8 @@ "be lost" msgstr "" "Выбранные привилегии будут установлены по умолчанию для каждой группы " -"пользователей. Учтите, что ранее установленные привилегии по умолчанию для " -"групп пользователей будут сброшены" +"пользователей. Учтите, что ранее установленные привилегии по умолчанию " +"для групп пользователей будут сброшены" #: kallithea/templates/admin/permissions/permissions_globals.html:46 msgid "Apply to all existing user groups" @@ -2864,7 +2879,8 @@ "mean nothing." msgstr "" "С этой опцией, право записи в группу репозиториев позволяет создавать " -"репозитории в этой группе. Без неё, право записи в группу не имеет действия." +"репозитории в этой группе. Без неё, право записи в группу не имеет " +"действия." #: kallithea/templates/admin/permissions/permissions_globals.html:68 msgid "User group creation" @@ -2873,7 +2889,8 @@ #: kallithea/templates/admin/permissions/permissions_globals.html:71 msgid "Enable this to allow non-admins to create user groups." msgstr "" -"Включите для возможности создавать группы пользователей любым пользователям." +"Включите для возможности создавать группы пользователей любым " +"пользователям." #: kallithea/templates/admin/permissions/permissions_globals.html:75 msgid "Repository forking" @@ -3067,8 +3084,8 @@ "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 "Remove this group" @@ -3132,8 +3149,8 @@ "Default revision for files page, downloads, full text search index and " "readme generation" msgstr "" -"Ревизия по умолчанию для страницы файлов, загрузки, полнотекстовый поисковый " -"индекс и генерация readme" +"Ревизия по умолчанию для страницы файлов, загрузки, полнотекстовый " +"поисковый индекс и генерация readme" #: kallithea/templates/admin/repos/repo_creating.html:9 #, python-format @@ -3361,8 +3378,8 @@ "группу, URL репозитория изменяется.\n" " Использование постоянного URL гарантирует, " "что данный репозиторий всегда будет доступен по этому URL.\n" -" Это может быть полезно в CI-системах, или в " -"любом другом случае, требующем встраивания URL в код ПО." +" Это может быть полезно в CI-системах, или " +"в любом другом случае, требующем встраивания URL в код ПО." #: kallithea/templates/admin/repos/repo_edit_settings.html:21 msgid "Remote repository" @@ -3509,7 +3526,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "Сохранить настройки" @@ -3548,7 +3565,8 @@ "related to repositories that no longer exist in the filesystem." msgstr "" "Отметьте для удаления всех комментариев, pull-запросов и других записей, " -"связанных с репозиториями, которые больше не существуют в файловой системе." +"связанных с репозиториями, которые больше не существуют в файловой " +"системе." #: kallithea/templates/admin/settings/settings_mapping.html:17 msgid "Invalidate cache for all repositories" @@ -3582,9 +3600,9 @@ "not seem to come from Kallithea. WARNING: This operation will destroy any " "custom git hooks you may have deployed by hand!" msgstr "" -"Перезаписывает все существующие хуки при установке хуков Git, даже если они " -"не поставляются с Kallithea. ПРЕДУПРЕЖДЕНИЕ: это действие уничтожит любые " -"Git хуки, которые могли быть созданы вручную!" +"Перезаписывает все существующие хуки при установке хуков Git, даже если " +"они не поставляются с Kallithea. ПРЕДУПРЕЖДЕНИЕ: это действие уничтожит " +"любые Git хуки, которые могли быть созданы вручную!" #: kallithea/templates/admin/settings/settings_mapping.html:41 msgid "Rescan Repositories" @@ -3687,8 +3705,8 @@ "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:4 msgid "General" @@ -3736,14 +3754,14 @@ "использовать следующие переменные:\n" " {scheme} " "используемый протокол, 'http' или 'https',\n" -" {email} e-mail " -"пользователя,\n" -" {md5email} хэш md5 " -"адреса почты пользователя (как на gravatar.com),\n" +" {email} e-" +"mail пользователя,\n" +" {md5email} хэш " +"md5 адреса почты пользователя (как на gravatar.com),\n" " {size} " "ожидаемый размер изображения,\n" -" {netloc} сетевой " -"путь/адрес хоста сервера Kallithea" +" {netloc} " +"сетевой путь/адрес хоста сервера Kallithea" #: kallithea/templates/admin/settings/settings_visual.html:40 msgid "HTTP Clone URL" @@ -3771,7 +3789,8 @@ "hostname\n" " " msgstr "" -"Схема URL для клонирования, например: '{scheme}://{user}@{netloc}/{repo}'.\n" +"Схема URL для клонирования, например: '{scheme}://{user}@{netloc}/" +"{repo}'.\n" " Доступны следующие " "переменные:\n" " {scheme} используемый " @@ -3782,8 +3801,8 @@ "адрес хоста сервера Kallithea,\n" " {repo} полное имя " "репозитория,\n" -" {repoid} ID репозитория, " -"может применяться для клонирования по идентификатору,\n" +" {repoid} ID " +"репозитория, может применяться для клонирования по идентификатору,\n" " {system_user} имя " "пользователя Kallithea в системе,\n" " {hostname} имя хоста " @@ -3799,53 +3818,54 @@ "Schema for constructing SSH clone URL, eg. 'ssh://{system_user}" "@{hostname}/{repo}'." msgstr "" -"Схема URL для клонирования по SSH, например: " -"'ssh://{system_user}@{hostname}/{repo}'." - -#: kallithea/templates/admin/settings/settings_visual.html:65 +"Схема URL для клонирования по SSH, например: 'ssh://{system_user}" +"@{hostname}/{repo}'." + +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "Размер страницы репозитория" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -"Количество элементов на странице репозитория до появления нумерации страниц." - -#: kallithea/templates/admin/settings/settings_visual.html:73 +"Количество элементов на странице репозитория до появления нумерации " +"страниц." + +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "Размер страницы администратора" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -"Количество элементов в сетке страницы администратора до появления нумерации " -"страниц." - -#: kallithea/templates/admin/settings/settings_visual.html:81 +"Количество элементов в сетке страницы администратора до появления " +"нумерации страниц." + +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "Иконки" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "Показывать иконки публичных репозиториев" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "Показывать иконки приватных репозиториев" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "Показывать иконки публичных репозиториев." -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "Метатегирование" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." @@ -3853,7 +3873,7 @@ "Анализирует мета-теги в поле описания репозитория и отображает их в виде " "цветных тегов." -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "Стилизовать обнаруженные мета-теги:" @@ -4191,7 +4211,8 @@ #: kallithea/templates/base/default_perms_box.html:35 msgid "Select this option to allow repository forking for this user" msgstr "" -"Выберите, чтобы разрешить данному пользователю создавать форки репозиториев" +"Выберите, чтобы разрешить данному пользователю создавать форки " +"репозиториев" #: kallithea/templates/base/perms_summary.html:13 #: kallithea/templates/changelog/changelog.html:41 @@ -4292,7 +4313,8 @@ #: kallithea/templates/base/root.html:46 msgid "Type name of user or member to grant permission" -msgstr "Введите имя пользователя или члена группы для предоставления доступа" +msgstr "" +"Введите имя пользователя или члена группы для предоставления доступа" #: kallithea/templates/base/root.html:47 msgid "Failed to revoke permission" @@ -4485,23 +4507,23 @@ msgid "Merge" msgstr "Слить" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "Перенесено из:" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "Трансплантировано из:" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "Заменено:" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "Предшествует:" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4511,7 +4533,7 @@ msgstr[1] "%s файлов изменено" msgstr[2] "%s файла изменено" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4521,8 +4543,8 @@ msgstr[1] "%s файла изменёно: %s добавления, %s удаления" msgstr[2] "%s файлов изменёно: %s добавлений, %s удалений" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -4841,15 +4863,16 @@ "Should you not be able to use the link above, please type the following " "code into the password reset form" msgstr "" -"В случае, если перейти по ссылке не удаётся, введите в форме сброса пароля " -"следующий код" +"В случае, если перейти по ссылке не удаётся, введите в форме сброса " +"пароля следующий код" #: kallithea/templates/email_templates/password_reset.html:44 msgid "" "If it weren't you who requested the password reset, just disregard this " "message." msgstr "" -"Если вы не запрашивали сброс пароля, то просто проигнорируйте это сообщение." +"Если вы не запрашивали сброс пароля, то просто проигнорируйте это " +"сообщение." #: kallithea/templates/email_templates/pull_request.html:4 #, python-format @@ -5285,7 +5308,8 @@ #: kallithea/templates/pullrequests/pullrequest_data.html:70 #, python-format msgid "Confirm again to delete this pull request with %s comments" -msgstr "Ещё раз подтвердите удаление pull-запроса со всеми (%s) комментариями" +msgstr "" +"Ещё раз подтвердите удаление pull-запроса со всеми (%s) комментариями" #: kallithea/templates/pullrequests/pullrequest_show.html:6 #, python-format @@ -5506,45 +5530,45 @@ msgid "Stats gathered: " msgstr "Полученная статистика: " -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "файлы" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "Показать еще" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "commit'ы" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "файлы добавлены" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "файлы изменены" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "файлы удалены" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "файлы удалены" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "commit" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "файл удалён" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "файл изменён" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "файл удалён" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/sk/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/sk/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/sk/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2015-04-01 12:59+0200\n" "Last-Translator: Andrej Shadura \n" "Language-Team: Slovak %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1245,34 +1245,36 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" @@ -1280,7 +1282,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" @@ -1288,7 +1290,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" @@ -1296,7 +1298,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" @@ -1304,7 +1306,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" @@ -1312,7 +1314,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" @@ -1320,27 +1322,27 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1349,135 +1351,135 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1666 #, fuzzy msgid "Only admins can fork repositories" msgstr "Repozitáre" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 #, fuzzy msgid "Non-admins can fork repositories" msgstr "Repozitáre" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1503,146 +1505,146 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Set changeset status" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "Zmeny" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2334,7 +2336,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3395,7 +3397,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3636,55 +3638,55 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "Repositories" msgid "Repository page size" msgstr "Repozitáre" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4317,23 +4319,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4343,7 +4345,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4353,8 +4355,8 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5342,45 +5344,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/tr/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/tr/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/tr/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.4.99\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-11-05 08:03+0000\n" "Last-Translator: Hüseyin Tunç \n" "Language-Team: Turkish %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1237,96 +1237,98 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "" @@ -1335,133 +1337,133 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1487,145 +1489,145 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" -msgstr "" - -#: kallithea/model/user.py:186 +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2314,7 +2316,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3357,7 +3359,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "" @@ -3597,53 +3599,53 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4271,23 +4273,23 @@ msgid "Merge" msgstr "" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4296,7 +4298,7 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4305,8 +4307,8 @@ msgstr[0] "" msgstr[1] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5266,45 +5268,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" +#: kallithea/templates/summary/statistics.html:403 +msgid "commits" +msgstr "" + +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + #: kallithea/templates/summary/statistics.html:405 -msgid "commits" +msgid "files changed" msgstr "" #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" +msgid "files removed" msgstr "" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" +msgid "commit" +msgstr "" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" msgstr "" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" +msgid "file changed" msgstr "" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/uk/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/uk/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/uk/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3.2\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-11-13 10:04+0000\n" "Last-Translator: Oleksandr Shtalinberg \n" "Language-Team: Ukrainian %s" msgstr "Показати всі комбіновані набори змін %s- >%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "Порівняйте вигляд" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "і" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "%s більше" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "редакції" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "Ім'я розгалуження %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "Pull request %s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "[видалений] репозиторій" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "[створено] репозиторій" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[створено] репозиторій як fork" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "[forked] репозиторій" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "[оновлено] репозиторій" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "[завантажити] архів з репозиторію" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "[видалити] репозиторій" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "[створено] користувач" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "[оновлений] користувач" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "[створено] групу користувачів" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "[оновлено] група користувачів" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "Файлів немає" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "новий файл" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "перейменувати" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "chmod" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1248,34 +1248,36 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" @@ -1283,7 +1285,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" @@ -1291,7 +1293,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" @@ -1299,7 +1301,7 @@ msgstr[1] "%d днів" msgstr[2] "%d дня" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" @@ -1307,7 +1309,7 @@ msgstr[1] "%d годин" msgstr[2] "%d години" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" @@ -1315,7 +1317,7 @@ msgstr[1] "%d хвилин" msgstr[2] "%d хвилини" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" @@ -1323,27 +1325,27 @@ msgstr[1] "%d секунд" msgstr[2] "%d секунди" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "в %s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "%s тому" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "у %s і %s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s і %s тому" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "прямо зараз" @@ -1352,137 +1354,137 @@ msgid "on line %s" msgstr "в рядку %s" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[Згадування]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "верхній рівень" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "Kallithea Адміністратор" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "Користувач за промовчанням не має доступу до нових репозиторіїв" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" -msgstr "Kallithea Адміністратор" - -#: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "Користувач за промовчанням не має доступу до нових репозиторіїв" - -#: kallithea/model/db.py:1640 msgid "Default user has read access to new repositories" msgstr "" "Користувач за замовчанням має доступ на перегляд нових репозиторіїв" -#: kallithea/model/db.py:1641 +#: kallithea/model/db.py:1638 msgid "Default user has write access to new repositories" msgstr "" "Користувач за замовчуванням має доступ до запису до нових репозиторіїв" -#: kallithea/model/db.py:1642 +#: kallithea/model/db.py:1639 msgid "Default user has admin access to new repositories" msgstr "" "Користувач за промовчанням має доступ адміністратора до нових репозиторіїв" -#: kallithea/model/db.py:1644 +#: kallithea/model/db.py:1641 msgid "Default user has no access to new repository groups" msgstr "" "Користувач за замовчуванням не має доступу до нових груп репозиторіїв" -#: kallithea/model/db.py:1645 +#: kallithea/model/db.py:1642 msgid "Default user has read access to new repository groups" msgstr "" +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1644 +msgid "Default user has admin access to new repository groups" +msgstr "" + #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" +msgid "Only admins can fork repositories" msgstr "" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" +msgid "Non-admins can fork repositories" msgstr "" #: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" +msgid "Registration disabled" msgstr "" #: kallithea/model/db.py:1667 -msgid "Non-admins can fork repositories" -msgstr "" - -#: kallithea/model/db.py:1669 -msgid "Registration disabled" -msgstr "" - -#: kallithea/model/db.py:1670 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 -msgid "Not reviewed" -msgstr "" - -#: kallithea/model/db.py:2207 -msgid "Under review" -msgstr "" - #: kallithea/model/db.py:2208 -msgid "Not approved" +msgid "Not reviewed" msgstr "" #: kallithea/model/db.py:2209 +msgid "Under review" +msgstr "" + +#: kallithea/model/db.py:2210 +msgid "Not approved" +msgstr "" + +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1508,145 +1510,145 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 -#, python-format -msgid "SSH key %r not found" -msgstr "" - -#: kallithea/model/user.py:186 +#: kallithea/model/ssh_key.py:88 +#, python-format +msgid "SSH key with fingerprint %r found" +msgstr "" + +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2336,7 +2338,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3402,7 +3404,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 msgid "Save Settings" msgstr "Зберегти налаштування" @@ -3660,11 +3662,11 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 msgid "Repository page size" msgstr "Розмір сторінки репозиторію" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." @@ -3672,11 +3674,11 @@ "Кількість елементів, що відображаються на сторінках сховища перед " "показаним нумерацією." -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "Розмір адмін сторінки" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." @@ -3684,33 +3686,33 @@ "Кількість елементів, що відображаються в сітках адміністратора сторінки " "до відображення нумерації." -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "Іконки" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "Показати піктограму загальнодоступного сховища на сховищах" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "Показати значок приватної репозиторію на репозиторіїв" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "Показати публічні/приватні значки поруч із назвами сховищ." -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 msgid "Meta Tagging" msgstr "Мета-теги" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4339,23 +4341,23 @@ msgid "Merge" msgstr "Злити" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "Замінено на:" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4365,7 +4367,7 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4375,8 +4377,8 @@ msgstr[1] "" msgstr[2] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5342,45 +5344,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "файли" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "Показати більше" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "" +#: kallithea/templates/summary/statistics.html:404 +msgid "files added" +msgstr "" + +#: kallithea/templates/summary/statistics.html:405 +msgid "files changed" +msgstr "файли змінено" + #: kallithea/templates/summary/statistics.html:406 -msgid "files added" -msgstr "" - -#: kallithea/templates/summary/statistics.html:407 -msgid "files changed" -msgstr "файли змінено" +msgid "files removed" +msgstr "вилучені файли" #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "вилучені файли" +msgid "commit" +msgstr "Фіксація" + +#: kallithea/templates/summary/statistics.html:409 +msgid "file added" +msgstr "файл додано" #: kallithea/templates/summary/statistics.html:410 -msgid "commit" -msgstr "Фіксація" +msgid "file changed" +msgstr "файл змінено" #: kallithea/templates/summary/statistics.html:411 -msgid "file added" -msgstr "файл додано" - -#: kallithea/templates/summary/statistics.html:412 -msgid "file changed" -msgstr "файл змінено" - -#: kallithea/templates/summary/statistics.html:413 msgid "file removed" msgstr "файл видалено" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2019-08-14 19:00+0000\n" "Last-Translator: Elizabeth Sherrock \n" "Language-Team: Chinese (Simplified) %s" msgstr "显示所有合并的修订集 %s->%s" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 #, fuzzy msgid "Compare view" msgstr "比较显示" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "还有" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "%s个" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "修订" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, fuzzy, python-format msgid "Fork name %s" msgstr "复刻名称%s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, fuzzy, python-format msgid "Pull request %s" msgstr "拉取请求#%s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "[删除]版本库" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "[创建]版本库" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "[创建]复刻版本库" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "[复刻]版本库" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "[更新]版本库" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "[删除]版本库" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "[创建]用户" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "[更新]用户" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "[评论]了版本库中的修订" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "[评论]拉取请求" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "[关闭] 拉取请求" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "[推送]到" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "[通过Kallithea提交]到版本库" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "[远程拉取]到版本库" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "[拉取]自" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "[开始关注]版本库" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "[停止关注]版本库" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr " 还有%s个" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "无文件" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1257,90 +1257,92 @@ "版本库%s没有映射到数据库,可能是从文件系统创建或者重命名,请重启Kallithea" "以重新扫描版本库" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d年" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "%d月" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d天" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d时" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d分" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d秒" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "%s" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "%s前" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "%s零%s" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "%s零%s前" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "刚才" @@ -1349,143 +1351,143 @@ msgid "on line %s" msgstr "在%s行" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "[提及]" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "Kallithea 管理员" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" -msgstr "Kallithea 管理员" - -#: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 #, fuzzy msgid "Default user has read access to new repositories" msgstr "未授权的资源访问" -#: kallithea/model/db.py:1641 +#: kallithea/model/db.py:1638 #, fuzzy msgid "Default user has write access to new repositories" msgstr "未授权的资源访问" +#: kallithea/model/db.py:1639 +msgid "Default user has admin access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1641 +msgid "Default user has no access to new repository groups" +msgstr "" + #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1654 #, fuzzy msgid "Only admins can create repository groups" msgstr "没有在该版本库组中创建版本库的权限" -#: kallithea/model/db.py:1655 +#: kallithea/model/db.py:1652 #, fuzzy msgid "Non-admins can create repository groups" msgstr "没有在该版本库组中创建版本库的权限" +#: kallithea/model/db.py:1654 +msgid "Only admins can create user groups" +msgstr "" + +#: kallithea/model/db.py:1655 +msgid "Non-admins can create user groups" +msgstr "" + #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1666 #, fuzzy msgid "Only admins can fork repositories" msgstr "创建版本库" -#: kallithea/model/db.py:1667 +#: kallithea/model/db.py:1664 #, fuzzy msgid "Non-admins can fork repositories" msgstr "创建版本库" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 #, fuzzy msgid "Not reviewed" msgstr "未检视" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 #, fuzzy msgid "Under review" msgstr "检视中" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 #, fuzzy #| msgid "Approved" msgid "Not approved" msgstr "已批准" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "已批准" @@ -1511,7 +1513,7 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, fuzzy, python-format #| msgid "[Comment] %(repo_name)s changeset %(short_id)s on %(branch)s" msgid "" @@ -1519,119 +1521,119 @@ "%(branch)s" msgstr "[评论] %(repo_name)s 修订集 %(short_id)s 在 %(branch)s" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, fuzzy, python-format msgid "New user %(new_username)s registered" msgstr "用户名称 %(new_username)s 无效" -#: kallithea/model/notification.py:169 +#: kallithea/model/notification.py:168 #, python-format msgid "" "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:170 +#: kallithea/model/notification.py:169 #, python-format msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 #, fuzzy msgid "Closing" msgstr "使用中" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 #, fuzzy #| msgid "Error creating pull request: %s" msgid "Cannot create empty pull request" msgstr "创建拉取请求出错:%s" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 #, fuzzy #| msgid "Confirm to delete this pull request" msgid "You are not authorized to create the pull request" msgstr "确认删除拉取请求" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 #, fuzzy #| msgid "Missing changesets since the previous pull request:" msgid "Missing changesets since the previous iteration:" msgstr "缺少上次拉取请求之后的修订集:" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, fuzzy, python-format #| msgid "New changesets on %s %s since the previous pull request:" msgid "New changesets on %s %s since the previous iteration:" msgstr "在上次拉取请求之后,在 %s %s 上的新修订集:" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, fuzzy, python-format #| msgid "New changesets on %s %s since the previous pull request:" msgid "No changes found on %s %s since previous iteration." msgstr "在上次拉取请求之后,在 %s %s 上的新修订集:" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "最新tip版本" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "未找到修订集" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 #, fuzzy msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "由于是系统帐号,无法删除该用户" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " @@ -1640,7 +1642,7 @@ "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本" "库。%s" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " @@ -1649,7 +1651,7 @@ "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本" "库。%s" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, fuzzy, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " @@ -1658,16 +1660,16 @@ "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本" "库。%s" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 #, fuzzy msgid "Password reset notification" msgstr "确认密码" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2367,7 +2369,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3462,7 +3464,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 #, fuzzy msgid "Save Settings" msgstr "保存设置" @@ -3711,57 +3713,57 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "repositories" msgid "Repository page size" msgstr "版本库" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "图标" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "显示公共版本库图标" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "显示私有版本库图标" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 #, fuzzy msgid "Show public/private icons next to repository names." msgstr "显示公共版本库图标" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 #, fuzzy msgid "Meta Tagging" msgstr "元标记" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4415,26 +4417,26 @@ msgid "Merge" msgstr "合并" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 #, fuzzy msgid "Grafted from:" msgstr "创建于" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 #, fuzzy msgid "Replaced by:" msgstr "创建于" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 #, fuzzy msgid "Preceded by:" msgstr "创建于" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4442,7 +4444,7 @@ msgid_plural "%s files changed" msgstr[0] "修改%s个文件" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4450,8 +4452,8 @@ msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "修改%s个文件包括%s行插入和%s行删除" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5474,45 +5476,45 @@ msgid "Stats gathered: " msgstr "已收集的统计: " -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "文件" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "提交" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "文件已添加" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "文件已更改" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "文件已删除" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "文件已删除" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "提交" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "文件已添加" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "文件已更改" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "文件已删除" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po --- a/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po Thu Feb 06 01:19:23 2020 +0100 @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: Kallithea 0.3\n" "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n" -"POT-Creation-Date: 2019-11-14 23:33+0100\n" +"POT-Creation-Date: 2020-02-06 01:19+0100\n" "PO-Revision-Date: 2017-03-10 18:26+0000\n" "Last-Translator: mao \n" "Language-Team: Chinese (Traditional) %s" msgstr "" -#: kallithea/lib/helpers.py:721 +#: kallithea/lib/helpers.py:714 msgid "Compare view" msgstr "" -#: kallithea/lib/helpers.py:740 +#: kallithea/lib/helpers.py:733 msgid "and" msgstr "和" -#: kallithea/lib/helpers.py:741 +#: kallithea/lib/helpers.py:734 #, python-format msgid "%s more" msgstr "" -#: kallithea/lib/helpers.py:742 +#: kallithea/lib/helpers.py:735 #: kallithea/templates/changelog/changelog.html:43 msgid "revisions" msgstr "修訂" -#: kallithea/lib/helpers.py:766 +#: kallithea/lib/helpers.py:759 #, python-format msgid "Fork name %s" msgstr "分支名稱 %s" -#: kallithea/lib/helpers.py:787 +#: kallithea/lib/helpers.py:780 #, python-format msgid "Pull request %s" msgstr "提取要求 %s" -#: kallithea/lib/helpers.py:797 +#: kallithea/lib/helpers.py:790 msgid "[deleted] repository" msgstr "" -#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811 +#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804 msgid "[created] repository" msgstr "" -#: kallithea/lib/helpers.py:801 +#: kallithea/lib/helpers.py:794 msgid "[created] repository as fork" msgstr "" -#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813 +#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806 msgid "[forked] repository" msgstr "" -#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815 +#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808 msgid "[updated] repository" msgstr "" -#: kallithea/lib/helpers.py:807 +#: kallithea/lib/helpers.py:800 msgid "[downloaded] archive from repository" msgstr "" -#: kallithea/lib/helpers.py:809 +#: kallithea/lib/helpers.py:802 msgid "[delete] repository" msgstr "" -#: kallithea/lib/helpers.py:817 +#: kallithea/lib/helpers.py:810 msgid "[created] user" msgstr "" -#: kallithea/lib/helpers.py:819 +#: kallithea/lib/helpers.py:812 msgid "[updated] user" msgstr "" -#: kallithea/lib/helpers.py:821 +#: kallithea/lib/helpers.py:814 msgid "[created] user group" msgstr "" -#: kallithea/lib/helpers.py:823 +#: kallithea/lib/helpers.py:816 msgid "[updated] user group" msgstr "" -#: kallithea/lib/helpers.py:825 +#: kallithea/lib/helpers.py:818 msgid "[commented] on revision in repository" msgstr "" -#: kallithea/lib/helpers.py:827 +#: kallithea/lib/helpers.py:820 msgid "[commented] on pull request for" msgstr "" -#: kallithea/lib/helpers.py:829 +#: kallithea/lib/helpers.py:822 msgid "[closed] pull request for" msgstr "" -#: kallithea/lib/helpers.py:831 +#: kallithea/lib/helpers.py:824 msgid "[pushed] into" msgstr "" -#: kallithea/lib/helpers.py:833 +#: kallithea/lib/helpers.py:826 msgid "[committed via Kallithea] into repository" msgstr "" -#: kallithea/lib/helpers.py:835 +#: kallithea/lib/helpers.py:828 msgid "[pulled from remote] into repository" msgstr "" -#: kallithea/lib/helpers.py:837 +#: kallithea/lib/helpers.py:830 msgid "[pulled] from" msgstr "" -#: kallithea/lib/helpers.py:839 +#: kallithea/lib/helpers.py:832 msgid "[started following] repository" msgstr "" -#: kallithea/lib/helpers.py:841 +#: kallithea/lib/helpers.py:834 msgid "[stopped following] repository" msgstr "" -#: kallithea/lib/helpers.py:961 +#: kallithea/lib/helpers.py:954 #, python-format msgid " and %s more" msgstr "" -#: kallithea/lib/helpers.py:965 +#: kallithea/lib/helpers.py:958 #: kallithea/templates/compare/compare_diff.html:69 #: kallithea/templates/pullrequests/pullrequest_show.html:297 msgid "No files" msgstr "" -#: kallithea/lib/helpers.py:990 +#: kallithea/lib/helpers.py:983 msgid "new file" msgstr "" -#: kallithea/lib/helpers.py:993 +#: kallithea/lib/helpers.py:986 msgid "mod" msgstr "" -#: kallithea/lib/helpers.py:996 +#: kallithea/lib/helpers.py:989 msgid "del" msgstr "" -#: kallithea/lib/helpers.py:999 +#: kallithea/lib/helpers.py:992 msgid "rename" msgstr "" -#: kallithea/lib/helpers.py:1004 +#: kallithea/lib/helpers.py:997 msgid "chmod" msgstr "" -#: kallithea/lib/helpers.py:1297 +#: kallithea/lib/helpers.py:1290 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from " @@ -1243,90 +1243,92 @@ "repositories" msgstr "" -#: kallithea/lib/ssh.py:71 +#: kallithea/lib/ssh.py:75 msgid "SSH key is missing" msgstr "" -#: kallithea/lib/ssh.py:75 -msgid "Incorrect SSH key - it must have both a key type and a base64 part" -msgstr "" - #: kallithea/lib/ssh.py:79 +msgid "" +"Incorrect SSH key - it must have both a key type and a base64 part, like " +"'ssh-rsa ASRNeaZu4FA...xlJp='" +msgstr "" + +#: kallithea/lib/ssh.py:83 msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'" msgstr "" -#: kallithea/lib/ssh.py:82 +#: kallithea/lib/ssh.py:86 #, python-format msgid "Incorrect SSH key - unexpected characters in base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:87 +#: kallithea/lib/ssh.py:91 #, python-format msgid "Incorrect SSH key - failed to decode base64 part %r" msgstr "" -#: kallithea/lib/ssh.py:90 +#: kallithea/lib/ssh.py:94 #, python-format msgid "Incorrect SSH key - base64 part is not %r as claimed but %r" msgstr "" -#: kallithea/lib/utils2.py:334 +#: kallithea/lib/utils2.py:242 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" -#: kallithea/lib/utils2.py:335 +#: kallithea/lib/utils2.py:243 #, python-format msgid "%d month" msgid_plural "%d months" msgstr[0] "" -#: kallithea/lib/utils2.py:336 +#: kallithea/lib/utils2.py:244 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" -#: kallithea/lib/utils2.py:337 +#: kallithea/lib/utils2.py:245 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" -#: kallithea/lib/utils2.py:338 +#: kallithea/lib/utils2.py:246 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" -#: kallithea/lib/utils2.py:339 +#: kallithea/lib/utils2.py:247 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" -#: kallithea/lib/utils2.py:355 +#: kallithea/lib/utils2.py:263 #, python-format msgid "in %s" msgstr "" -#: kallithea/lib/utils2.py:357 +#: kallithea/lib/utils2.py:265 #, python-format msgid "%s ago" msgstr "" -#: kallithea/lib/utils2.py:359 +#: kallithea/lib/utils2.py:267 #, python-format msgid "in %s and %s" msgstr "" -#: kallithea/lib/utils2.py:362 +#: kallithea/lib/utils2.py:270 #, python-format msgid "%s and %s ago" msgstr "" -#: kallithea/lib/utils2.py:365 +#: kallithea/lib/utils2.py:273 msgid "just now" msgstr "現在" @@ -1335,134 +1337,134 @@ msgid "on line %s" msgstr "" -#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114 +#: kallithea/model/comment.py:219 kallithea/model/pull_request.py:112 msgid "[Mention]" msgstr "" -#: kallithea/model/db.py:1496 +#: kallithea/model/db.py:1493 msgid "top level" msgstr "" +#: kallithea/model/db.py:1634 +msgid "Kallithea Administrator" +msgstr "" + +#: kallithea/model/db.py:1636 +msgid "Default user has no access to new repositories" +msgstr "" + #: kallithea/model/db.py:1637 -msgid "Kallithea Administrator" +msgid "Default user has read access to new repositories" +msgstr "" + +#: kallithea/model/db.py:1638 +msgid "Default user has write access to new repositories" msgstr "" #: kallithea/model/db.py:1639 -msgid "Default user has no access to new repositories" -msgstr "" - -#: kallithea/model/db.py:1640 -msgid "Default user has read access to new repositories" +msgid "Default user has admin access to new repositories" msgstr "" #: kallithea/model/db.py:1641 -msgid "Default user has write access to new repositories" +msgid "Default user has no access to new repository groups" msgstr "" #: kallithea/model/db.py:1642 -msgid "Default user has admin access to new repositories" +msgid "Default user has read access to new repository groups" +msgstr "" + +#: kallithea/model/db.py:1643 +msgid "Default user has write access to new repository groups" msgstr "" #: kallithea/model/db.py:1644 -msgid "Default user has no access to new repository groups" -msgstr "" - -#: kallithea/model/db.py:1645 -msgid "Default user has read access to new repository groups" +msgid "Default user has admin access to new repository groups" msgstr "" #: kallithea/model/db.py:1646 -msgid "Default user has write access to new repository groups" +msgid "Default user has no access to new user groups" msgstr "" #: kallithea/model/db.py:1647 -msgid "Default user has admin access to new repository groups" +msgid "Default user has read access to new user groups" +msgstr "" + +#: kallithea/model/db.py:1648 +msgid "Default user has write access to new user groups" msgstr "" #: kallithea/model/db.py:1649 -msgid "Default user has no access to new user groups" -msgstr "" - -#: kallithea/model/db.py:1650 -msgid "Default user has read access to new user groups" +msgid "Default user has admin access to new user groups" msgstr "" #: kallithea/model/db.py:1651 -msgid "Default user has write access to new user groups" +msgid "Only admins can create repository groups" msgstr "" #: kallithea/model/db.py:1652 -msgid "Default user has admin access to new user groups" +msgid "Non-admins can create repository groups" msgstr "" #: kallithea/model/db.py:1654 -msgid "Only admins can create repository groups" +msgid "Only admins can create user groups" msgstr "" #: kallithea/model/db.py:1655 -msgid "Non-admins can create repository groups" +msgid "Non-admins can create user groups" msgstr "" #: kallithea/model/db.py:1657 -msgid "Only admins can create user groups" +msgid "Only admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1658 -msgid "Non-admins can create user groups" +msgid "Non-admins can create top level repositories" msgstr "" #: kallithea/model/db.py:1660 -msgid "Only admins can create top level repositories" +msgid "" +"Repository creation enabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1661 -msgid "Non-admins can create top level repositories" +msgid "" +"Repository creation disabled with write permission to a repository group" msgstr "" #: kallithea/model/db.py:1663 -msgid "" -"Repository creation enabled with write permission to a repository group" -msgstr "" +msgid "Only admins can fork repositories" +msgstr "祗有管理者才能分歧版本庫" #: kallithea/model/db.py:1664 -msgid "" -"Repository creation disabled with write permission to a repository group" -msgstr "" - -#: kallithea/model/db.py:1666 -msgid "Only admins can fork repositories" -msgstr "祗有管理者才能分歧版本庫" - -#: kallithea/model/db.py:1667 #, fuzzy msgid "Non-admins can fork repositories" msgstr "建立版本庫" -#: kallithea/model/db.py:1669 +#: kallithea/model/db.py:1666 msgid "Registration disabled" msgstr "" -#: kallithea/model/db.py:1670 +#: kallithea/model/db.py:1667 msgid "User registration with manual account activation" msgstr "" -#: kallithea/model/db.py:1671 +#: kallithea/model/db.py:1668 msgid "User registration with automatic account activation" msgstr "" -#: kallithea/model/db.py:2206 +#: kallithea/model/db.py:2208 msgid "Not reviewed" msgstr "未審核" -#: kallithea/model/db.py:2207 +#: kallithea/model/db.py:2209 msgid "Under review" msgstr "審核中" -#: kallithea/model/db.py:2208 +#: kallithea/model/db.py:2210 msgid "Not approved" msgstr "" -#: kallithea/model/db.py:2209 +#: kallithea/model/db.py:2211 msgid "Approved" msgstr "" @@ -1488,146 +1490,146 @@ msgid "Name must not contain only digits" msgstr "" -#: kallithea/model/notification.py:164 +#: kallithea/model/notification.py:163 #, python-format msgid "" "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on " "%(branch)s" msgstr "" -#: kallithea/model/notification.py:167 +#: kallithea/model/notification.py:166 #, python-format msgid "New user %(new_username)s registered" msgstr "" +#: kallithea/model/notification.py:168 +#, python-format +msgid "" +"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " +"%(pr_source_branch)s by %(pr_owner_username)s" +msgstr "" + #: kallithea/model/notification.py:169 #, python-format msgid "" -"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " -"%(pr_source_branch)s by %(pr_owner_username)s" -msgstr "" - -#: kallithea/model/notification.py:170 -#, python-format -msgid "" "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from " "%(pr_source_branch)s by %(pr_owner_username)s" msgstr "" -#: kallithea/model/notification.py:183 +#: kallithea/model/notification.py:189 msgid "Closing" msgstr "關閉中" -#: kallithea/model/pull_request.py:73 +#: kallithea/model/pull_request.py:72 #, python-format msgid "" "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s" msgstr "" -#: kallithea/model/pull_request.py:209 +#: kallithea/model/pull_request.py:207 msgid "Cannot create empty pull request" msgstr "" -#: kallithea/model/pull_request.py:217 +#: kallithea/model/pull_request.py:215 #, python-format msgid "" "Cannot create pull request - criss cross merge detected, please merge a " "later %s revision to %s" msgstr "" -#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380 +#: kallithea/model/pull_request.py:243 kallithea/model/pull_request.py:378 msgid "You are not authorized to create the pull request" msgstr "" -#: kallithea/model/pull_request.py:339 +#: kallithea/model/pull_request.py:337 msgid "Missing changesets since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:346 +#: kallithea/model/pull_request.py:344 #, python-format msgid "New changesets on %s %s since the previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:353 +#: kallithea/model/pull_request.py:351 msgid "Ancestor didn't change - diff since previous iteration:" msgstr "" -#: kallithea/model/pull_request.py:360 +#: kallithea/model/pull_request.py:358 #, python-format msgid "" "This iteration is based on another %s revision and there is no simple " "diff." msgstr "" -#: kallithea/model/pull_request.py:362 +#: kallithea/model/pull_request.py:360 #, python-format msgid "No changes found on %s %s since previous iteration." msgstr "" -#: kallithea/model/pull_request.py:388 +#: kallithea/model/pull_request.py:386 #, python-format msgid "Closed, next iteration: %s ." msgstr "" -#: kallithea/model/scm.py:668 +#: kallithea/model/scm.py:655 msgid "latest tip" msgstr "" -#: kallithea/model/ssh_key.py:56 +#: kallithea/model/ssh_key.py:57 #, python-format msgid "SSH key %r is invalid: %s" msgstr "" -#: kallithea/model/ssh_key.py:68 +#: kallithea/model/ssh_key.py:69 #, python-format msgid "SSH key %s is already used by %s" msgstr "" -#: kallithea/model/ssh_key.py:89 +#: kallithea/model/ssh_key.py:88 #, fuzzy, python-format #| msgid "Set changeset status" -msgid "SSH key %r not found" +msgid "SSH key with fingerprint %r found" msgstr "尚未有任何變更" -#: kallithea/model/user.py:186 +#: kallithea/model/user.py:184 msgid "New user registration" msgstr "" -#: kallithea/model/user.py:250 +#: kallithea/model/user.py:248 msgid "" "You can't remove this user since it is crucial for the entire application" msgstr "您無法移除這個使用者,因為係供整個應用使用" -#: kallithea/model/user.py:255 +#: kallithea/model/user.py:253 #, python-format msgid "" "User \"%s\" still owns %s repositories and cannot be removed. Switch " "owners or remove those repositories: %s" msgstr "" -#: kallithea/model/user.py:260 +#: kallithea/model/user.py:258 #, python-format msgid "" "User \"%s\" still owns %s repository groups and cannot be removed. Switch " "owners or remove those repository groups: %s" msgstr "" -#: kallithea/model/user.py:267 +#: kallithea/model/user.py:265 #, python-format msgid "" "User \"%s\" still owns %s user groups and cannot be removed. Switch " "owners or remove those user groups: %s" msgstr "" -#: kallithea/model/user.py:361 +#: kallithea/model/user.py:359 msgid "Password reset link" msgstr "" -#: kallithea/model/user.py:408 +#: kallithea/model/user.py:406 msgid "Password reset notification" msgstr "" -#: kallithea/model/user.py:409 +#: kallithea/model/user.py:407 #, python-format msgid "" "The password to your account %s has been changed using password reset " @@ -2325,7 +2327,7 @@ #: kallithea/templates/admin/repos/repo_edit_settings.html:100 #: kallithea/templates/admin/settings/settings_global.html:50 #: kallithea/templates/admin/settings/settings_vcs.html:66 -#: kallithea/templates/admin/settings/settings_visual.html:127 +#: kallithea/templates/admin/settings/settings_visual.html:129 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89 #: kallithea/templates/admin/users/user_edit_api_keys.html:14 #: kallithea/templates/admin/users/user_edit_api_keys.html:73 @@ -3410,7 +3412,7 @@ #: kallithea/templates/admin/settings/settings_global.html:49 #: kallithea/templates/admin/settings/settings_vcs.html:65 -#: kallithea/templates/admin/settings/settings_visual.html:126 +#: kallithea/templates/admin/settings/settings_visual.html:128 #, fuzzy msgid "Save Settings" msgstr "儲存設定" @@ -3658,56 +3660,56 @@ "@{hostname}/{repo}'." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:65 +#: kallithea/templates/admin/settings/settings_visual.html:67 #, fuzzy #| msgid "repositories" msgid "Repository page size" msgstr "個版本庫" -#: kallithea/templates/admin/settings/settings_visual.html:68 +#: kallithea/templates/admin/settings/settings_visual.html:70 msgid "" "Number of items displayed in the repository pages before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:73 +#: kallithea/templates/admin/settings/settings_visual.html:75 msgid "Admin page size" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:76 +#: kallithea/templates/admin/settings/settings_visual.html:78 msgid "" "Number of items displayed in the admin pages grids before pagination is " "shown." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:81 +#: kallithea/templates/admin/settings/settings_visual.html:83 msgid "Icons" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:86 +#: kallithea/templates/admin/settings/settings_visual.html:88 msgid "Show public repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:92 +#: kallithea/templates/admin/settings/settings_visual.html:94 msgid "Show private repository icon on repositories" msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:95 +#: kallithea/templates/admin/settings/settings_visual.html:97 msgid "Show public/private icons next to repository names." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:100 +#: kallithea/templates/admin/settings/settings_visual.html:102 #, fuzzy msgid "Meta Tagging" msgstr "設定" -#: kallithea/templates/admin/settings/settings_visual.html:105 +#: kallithea/templates/admin/settings/settings_visual.html:107 msgid "" "Parses meta tags from the repository description field and turns them " "into colored tags." msgstr "" -#: kallithea/templates/admin/settings/settings_visual.html:109 +#: kallithea/templates/admin/settings/settings_visual.html:111 msgid "Stylify recognised meta tags:" msgstr "" @@ -4349,23 +4351,23 @@ msgid "Merge" msgstr "合併" -#: kallithea/templates/changeset/changeset.html:96 +#: kallithea/templates/changeset/changeset.html:95 msgid "Grafted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:102 +#: kallithea/templates/changeset/changeset.html:100 msgid "Transplanted from:" msgstr "" -#: kallithea/templates/changeset/changeset.html:108 +#: kallithea/templates/changeset/changeset.html:106 msgid "Replaced by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:122 +#: kallithea/templates/changeset/changeset.html:120 msgid "Preceded by:" msgstr "" -#: kallithea/templates/changeset/changeset.html:139 +#: kallithea/templates/changeset/changeset.html:137 #: kallithea/templates/compare/compare_diff.html:59 #: kallithea/templates/pullrequests/pullrequest_show.html:290 #, python-format @@ -4373,7 +4375,7 @@ msgid_plural "%s files changed" msgstr[0] "" -#: kallithea/templates/changeset/changeset.html:141 +#: kallithea/templates/changeset/changeset.html:139 #: kallithea/templates/compare/compare_diff.html:61 #: kallithea/templates/pullrequests/pullrequest_show.html:292 #, python-format @@ -4381,8 +4383,8 @@ msgid_plural "%s files changed with %s insertions and %s deletions" msgstr[0] "" -#: kallithea/templates/changeset/changeset.html:154 -#: kallithea/templates/changeset/changeset.html:173 +#: kallithea/templates/changeset/changeset.html:152 +#: kallithea/templates/changeset/changeset.html:171 #: kallithea/templates/compare/compare_diff.html:81 #: kallithea/templates/pullrequests/pullrequest_show.html:309 #: kallithea/templates/pullrequests/pullrequest_show.html:333 @@ -5385,45 +5387,45 @@ msgid "Stats gathered: " msgstr "" -#: kallithea/templates/summary/statistics.html:87 -#: kallithea/templates/summary/summary.html:371 +#: kallithea/templates/summary/statistics.html:85 +#: kallithea/templates/summary/summary.html:369 msgid "files" msgstr "檔案" -#: kallithea/templates/summary/statistics.html:111 -#: kallithea/templates/summary/summary.html:401 +#: kallithea/templates/summary/statistics.html:109 +#: kallithea/templates/summary/summary.html:399 msgid "Show more" msgstr "" -#: kallithea/templates/summary/statistics.html:405 +#: kallithea/templates/summary/statistics.html:403 msgid "commits" msgstr "遞交" -#: kallithea/templates/summary/statistics.html:406 +#: kallithea/templates/summary/statistics.html:404 msgid "files added" msgstr "多個檔案新增" -#: kallithea/templates/summary/statistics.html:407 +#: kallithea/templates/summary/statistics.html:405 msgid "files changed" msgstr "多個檔案修改" +#: kallithea/templates/summary/statistics.html:406 +msgid "files removed" +msgstr "移除多個檔案" + #: kallithea/templates/summary/statistics.html:408 -msgid "files removed" -msgstr "移除多個檔案" - -#: kallithea/templates/summary/statistics.html:410 msgid "commit" msgstr "遞交" -#: kallithea/templates/summary/statistics.html:411 +#: kallithea/templates/summary/statistics.html:409 msgid "file added" msgstr "檔案新增" -#: kallithea/templates/summary/statistics.html:412 +#: kallithea/templates/summary/statistics.html:410 msgid "file changed" msgstr "檔案修改" -#: kallithea/templates/summary/statistics.html:413 +#: kallithea/templates/summary/statistics.html:411 msgid "file removed" msgstr "移除檔案" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/annotate.py --- a/kallithea/lib/annotate.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/annotate.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,16 +25,15 @@ :license: GPLv3, see LICENSE.md for more details. """ -import StringIO - from pygments import highlight from pygments.formatters import HtmlFormatter from kallithea.lib.vcs.exceptions import VCSError from kallithea.lib.vcs.nodes import FileNode +from kallithea.lib.vcs.utils import safe_str -def annotate_highlight(filenode, annotate_from_changeset_func=None, +def annotate_highlight(filenode, annotate_from_changeset_func, order=None, headers=None, **options): """ Returns html portion containing annotated table with 3 columns: line @@ -51,26 +50,26 @@ """ from kallithea.lib.pygmentsutils import get_custom_lexer options['linenos'] = True - formatter = AnnotateHtmlFormatter(filenode=filenode, order=order, - headers=headers, - annotate_from_changeset_func=annotate_from_changeset_func, **options) + formatter = AnnotateHtmlFormatter(filenode=filenode, + annotate_from_changeset_func=annotate_from_changeset_func, order=order, + headers=headers, **options) lexer = get_custom_lexer(filenode.extension) or filenode.lexer - highlighted = highlight(filenode.content, lexer, formatter) + highlighted = highlight(safe_str(filenode.content), lexer, formatter) return highlighted class AnnotateHtmlFormatter(HtmlFormatter): - def __init__(self, filenode, annotate_from_changeset_func=None, + def __init__(self, filenode, annotate_from_changeset_func, order=None, **options): """ - If ``annotate_from_changeset_func`` is passed it should be a function + ``annotate_from_changeset_func`` must be a function which returns string from the given changeset. For example, we may pass following function as ``annotate_from_changeset_func``:: def changeset_to_anchor(changeset): return '%s\n' % \ - (changeset.id, changeset.id) + (changeset.raw_id, changeset.raw_id) :param annotate_from_changeset_func: see above :param order: (default: ``['ls', 'annotate', 'code']``); order of @@ -101,22 +100,13 @@ raise VCSError("This formatter expect FileNode parameter, not %r" % type(filenode)) - def annotate_from_changeset(self, changeset): - """ - Returns full html line for single changeset per annotated line. - """ - if self.annotate_from_changeset_func: - return self.annotate_from_changeset_func(changeset) - else: - return ''.join((changeset.id, '\n')) - def _wrap_tablelinenos(self, inner): - dummyoutfile = StringIO.StringIO() + inner_lines = [] lncount = 0 for t, line in inner: if t: lncount += 1 - dummyoutfile.write(line) + inner_lines.append(line) fl = self.linenostart mw = len(str(lncount + fl - 1)) @@ -166,7 +156,7 @@ # ln_ = len(ls.splitlines()) # if ln_cs > ln_: # annotate_changesets = annotate_changesets[:ln_ - ln_cs] - annotate = ''.join((self.annotate_from_changeset(el[2]()) + annotate = ''.join((self.annotate_from_changeset_func(el[2]()) for el in self.filenode.annotate)) # in case you wonder about the seemingly redundant
here: # since the content in the other cell also is wrapped in a div, @@ -176,7 +166,7 @@ '
' +
                   ls + '
' + '') - yield 0, dummyoutfile.getvalue() + yield 0, ''.join(inner_lines) yield 0, '' ''' @@ -204,5 +194,5 @@ ''.join(headers_row) + ''.join(body_row_start) ) - yield 0, dummyoutfile.getvalue() + yield 0, ''.join(inner_lines) yield 0, '' diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/app_globals.py --- a/kallithea/lib/app_globals.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/app_globals.py Thu Feb 06 01:19:23 2020 +0100 @@ -39,9 +39,7 @@ """One instance of Globals is created during application initialization and is available during requests via the 'app_globals' variable - """ - self.available_permissions = None # propagated after init_model @property def cache(self): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/auth.py --- a/kallithea/lib/auth.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/auth.py Thu Feb 06 01:19:23 2020 +0100 @@ -28,6 +28,7 @@ import itertools import logging import os +import string import ipaddr from decorator import decorator @@ -41,7 +42,7 @@ from kallithea.config.routing import url from kallithea.lib.caching_query import FromCache from kallithea.lib.utils import conditional_cache, get_repo_group_slug, get_repo_slug, get_user_group_slug -from kallithea.lib.utils2 import safe_str, safe_unicode +from kallithea.lib.utils2 import ascii_bytes, ascii_str, safe_bytes from kallithea.lib.vcs.utils.lazy import LazyProperty from kallithea.model.db import ( Permission, RepoGroup, Repository, User, UserApiKeys, UserGroup, UserGroupMember, UserGroupRepoGroupToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupUserGroupToPerm, UserIpMap, UserToPerm) @@ -95,7 +96,7 @@ return hashlib.sha256(password).hexdigest() elif is_unix: import bcrypt - return bcrypt.hashpw(safe_str(password), bcrypt.gensalt(10)) + return ascii_str(bcrypt.hashpw(safe_bytes(password), bcrypt.gensalt(10))) else: raise Exception('Unknown or unsupported platform %s' % __platform__) @@ -109,13 +110,14 @@ :param password: password :param hashed: password in hashed form """ - - if is_windows: - return hashlib.sha256(password).hexdigest() == hashed + # sha256 hashes will always be 64 hex chars + # bcrypt hashes will always contain $ (and be shorter) + if is_windows or len(hashed) == 64 and all(x in string.hexdigits for x in hashed): + return hashlib.sha256(safe_bytes(password)).hexdigest() == hashed elif is_unix: import bcrypt try: - return bcrypt.checkpw(safe_str(password), safe_str(hashed)) + return bcrypt.checkpw(safe_bytes(password), ascii_bytes(hashed)) except ValueError as e: # bcrypt will throw ValueError 'Invalid hashed_password salt' on all password errors log.error('error from bcrypt checking password: %s', e) @@ -440,7 +442,7 @@ self.is_default_user = False else: # copy non-confidential database fields from a `db.User` to this `AuthUser`. - for k, v in dbuser.get_dict().iteritems(): + for k, v in dbuser.get_dict().items(): assert k not in ['api_keys', 'permissions'] setattr(self, k, v) self.is_default_user = dbuser.is_default_user @@ -523,7 +525,7 @@ """ Returns list of repositories you're an admin of """ - return [x[0] for x in self.permissions['repositories'].iteritems() + return [x[0] for x in self.permissions['repositories'].items() if x[1] == 'repository.admin'] @property @@ -531,7 +533,7 @@ """ Returns list of repository groups you're an admin of """ - return [x[0] for x in self.permissions['repositories_groups'].iteritems() + return [x[0] for x in self.permissions['repositories_groups'].items() if x[1] == 'group.admin'] @property @@ -539,11 +541,11 @@ """ Returns list of user groups you're an admin of """ - return [x[0] for x in self.permissions['user_groups'].iteritems() + return [x[0] for x in self.permissions['user_groups'].items() if x[1] == 'usergroup.admin'] def __repr__(self): - return "" % (self.user_id, self.username) + return "<%s %s: %r>" % (self.__class__.__name__, self.user_id, self.username) def to_cookie(self): """ Serializes this login session to a cookie `dict`. """ @@ -594,24 +596,6 @@ return _set or set(['0.0.0.0/0', '::/0']) -def set_available_permissions(config): - """ - This function will propagate globals with all available defined - permission given in db. We don't want to check each time from db for new - permissions since adding a new permission also requires application restart - ie. to decorate new views with the newly created permission - - :param config: current config instance - - """ - log.info('getting information about all available permissions') - try: - all_perms = Session().query(Permission).all() - config['available_permissions'] = [x.permission_name for x in all_perms] - finally: - Session.remove() - - #============================================================================== # CHECK DECORATORS #============================================================================== @@ -776,7 +760,7 @@ def __init__(self, *required_perms): self.required_perms = required_perms # usually very short - a list is thus fine - def __nonzero__(self): + def __bool__(self): """ Defend against accidentally forgetting to call the object and instead evaluating it directly in a boolean context, which could have security implications. @@ -833,10 +817,6 @@ self.required_perms = set(perms) def __call__(self, authuser, repo_name, purpose=None): - # repo_name MUST be unicode, since we handle keys in ok - # dict by unicode - repo_name = safe_unicode(repo_name) - try: ok = authuser.permissions['repositories'][repo_name] in self.required_perms except KeyError: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/auth_modules/__init__.py --- a/kallithea/lib/auth_modules/__init__.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/auth_modules/__init__.py Thu Feb 06 01:19:23 2020 +0100 @@ -309,7 +309,7 @@ "a subclass of %s" % (plugin, KallitheaAuthPluginBase)) plugin = pluginclass() - if plugin.plugin_settings.im_func != KallitheaAuthPluginBase.plugin_settings.im_func: + if plugin.plugin_settings.__func__ != KallitheaAuthPluginBase.plugin_settings: raise TypeError("Authentication class %s.KallitheaAuthPluginBase " "has overridden the plugin_settings method, which is " "forbidden." % plugin) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/auth_modules/auth_container.py --- a/kallithea/lib/auth_modules/auth_container.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/auth_modules/auth_container.py Thu Feb 06 01:19:23 2020 +0100 @@ -29,7 +29,7 @@ from kallithea.lib import auth_modules from kallithea.lib.compat import hybrid_property -from kallithea.lib.utils2 import safe_str, safe_unicode, str2bool +from kallithea.lib.utils2 import str2bool from kallithea.model.db import Setting @@ -180,7 +180,7 @@ # only way to log in is using environ username = None if userobj: - username = safe_str(getattr(userobj, 'username')) + username = getattr(userobj, 'username') if not username: # we don't have any objects in DB, user doesn't exist, extract @@ -199,8 +199,8 @@ user_data = { 'username': username, - 'firstname': safe_unicode(firstname or username), - 'lastname': safe_unicode(lastname or ''), + 'firstname': firstname or username, + 'lastname': lastname or '', 'groups': [], 'email': email or '', 'admin': admin or False, diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/auth_modules/auth_crowd.py --- a/kallithea/lib/auth_modules/auth_crowd.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/auth_modules/auth_crowd.py Thu Feb 06 01:19:23 2020 +0100 @@ -28,10 +28,12 @@ import base64 import logging -import urllib2 +import urllib.parse +import urllib.request -from kallithea.lib import auth_modules -from kallithea.lib.compat import formatted_json, hybrid_property, json +from kallithea.lib import auth_modules, ext_json +from kallithea.lib.compat import hybrid_property +from kallithea.lib.utils2 import ascii_bytes, ascii_str, safe_bytes log = logging.getLogger(__name__) @@ -71,10 +73,10 @@ self._make_opener() def _make_opener(self): - mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() + mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() mgr.add_password(None, self._uri, self.user, self.passwd) - handler = urllib2.HTTPBasicAuthHandler(mgr) - self.opener = urllib2.build_opener(handler) + handler = urllib.request.HTTPBasicAuthHandler(mgr) + self.opener = urllib.request.build_opener(handler) def _request(self, url, body=None, headers=None, method=None, noformat=False, @@ -82,14 +84,12 @@ _headers = {"Content-type": "application/json", "Accept": "application/json"} if self.user and self.passwd: - authstring = base64.b64encode("%s:%s" % (self.user, self.passwd)) + authstring = ascii_str(base64.b64encode(safe_bytes("%s:%s" % (self.user, self.passwd)))) _headers["Authorization"] = "Basic %s" % authstring if headers: _headers.update(headers) - log.debug("Sent crowd: \n%s", - formatted_json({"url": url, "body": body, - "headers": _headers})) - req = urllib2.Request(url, body, _headers) + log.debug("Sent to crowd at %s:\nHeaders: %s\nBody:\n%s", url, _headers, body) + req = urllib.request.Request(url, body, _headers) if method: req.get_method = lambda: method @@ -103,7 +103,7 @@ rval["status"] = True rval["error"] = "Response body was empty" elif not noformat: - rval = json.loads(msg) + rval = ext_json.loads(msg) rval["status"] = True else: rval = "".join(rdoc.readlines()) @@ -120,14 +120,14 @@ """Authenticate a user against crowd. Returns brief information about the user.""" url = ("%s/rest/usermanagement/%s/authentication?username=%s" - % (self._uri, self._version, urllib2.quote(username))) - body = json.dumps({"value": password}) + % (self._uri, self._version, urllib.parse.quote(username))) + body = ascii_bytes(ext_json.dumps({"value": password})) return self._request(url, body) def user_groups(self, username): """Retrieve a list of groups to which this user belongs.""" url = ("%s/rest/usermanagement/%s/user/group/nested?username=%s" - % (self._uri, self._version, urllib2.quote(username))) + % (self._uri, self._version, urllib.parse.quote(username))) return self._request(url) @@ -209,11 +209,11 @@ log.debug('Empty username or password skipping...') return None - log.debug("Crowd settings: \n%s", formatted_json(settings)) + log.debug("Crowd settings: %s", settings) server = CrowdServer(**settings) server.set_credentials(settings["app_name"], settings["app_password"]) crowd_user = server.user_auth(username, password) - log.debug("Crowd returned: \n%s", formatted_json(crowd_user)) + log.debug("Crowd returned: %s", crowd_user) if not crowd_user["status"]: log.error('Crowd authentication as %s returned no status', username) return None @@ -223,7 +223,7 @@ return None res = server.user_groups(crowd_user["name"]) - log.debug("Crowd groups: \n%s", formatted_json(res)) + log.debug("Crowd groups: %s", res) crowd_user["groups"] = [x["name"] for x in res["groups"]] # old attrs fetched from Kallithea database @@ -246,7 +246,7 @@ for group in settings["admin_groups"].split(","): if group in user_data["groups"]: user_data["admin"] = True - log.debug("Final crowd user object: \n%s", formatted_json(user_data)) + log.debug("Final crowd user object: %s", user_data) log.info('user %s authenticated correctly', user_data['username']) return user_data diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/auth_modules/auth_internal.py --- a/kallithea/lib/auth_modules/auth_internal.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/auth_modules/auth_internal.py Thu Feb 06 01:19:23 2020 +0100 @@ -30,7 +30,6 @@ from kallithea.lib import auth_modules from kallithea.lib.compat import formatted_json, hybrid_property -from kallithea.model.db import User log = logging.getLogger(__name__) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/auth_modules/auth_ldap.py --- a/kallithea/lib/auth_modules/auth_ldap.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/auth_modules/auth_ldap.py Thu Feb 06 01:19:23 2020 +0100 @@ -31,7 +31,6 @@ from kallithea.lib import auth_modules from kallithea.lib.compat import hybrid_property from kallithea.lib.exceptions import LdapConnectionError, LdapImportError, LdapPasswordError, LdapUsernameError -from kallithea.lib.utils2 import safe_str, safe_unicode log = logging.getLogger(__name__) @@ -70,11 +69,11 @@ port) for host in server.split(','))) - self.LDAP_BIND_DN = safe_str(bind_dn) - self.LDAP_BIND_PASS = safe_str(bind_pass) + self.LDAP_BIND_DN = bind_dn + self.LDAP_BIND_PASS = bind_pass - self.BASE_DN = safe_str(base_dn) - self.LDAP_FILTER = safe_str(ldap_filter) + self.BASE_DN = base_dn + self.LDAP_FILTER = ldap_filter self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope) self.attr_login = attr_login @@ -139,7 +138,7 @@ try: log.debug('Trying simple bind with %s', dn) - server.simple_bind_s(dn, safe_str(password)) + server.simple_bind_s(dn, password) results = server.search_ext_s(dn, ldap.SCOPE_BASE, '(objectClass=*)') if len(results) == 1: @@ -338,8 +337,8 @@ user_data = { 'username': username, - 'firstname': safe_unicode(get_ldap_attr('attr_firstname') or firstname), - 'lastname': safe_unicode(get_ldap_attr('attr_lastname') or lastname), + 'firstname': get_ldap_attr('attr_firstname') or firstname, + 'lastname': get_ldap_attr('attr_lastname') or lastname, 'groups': [], 'email': get_ldap_attr('attr_email') or email, 'admin': admin, diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/base.py --- a/kallithea/lib/base.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/base.py Thu Feb 06 01:19:23 2020 +0100 @@ -28,9 +28,9 @@ :license: GPLv3, see LICENSE.md for more details. """ +import base64 import datetime import logging -import time import traceback import warnings @@ -45,12 +45,11 @@ from kallithea import BACKENDS, __version__ from kallithea.config.routing import url -from kallithea.lib import auth_modules +from kallithea.lib import auth_modules, ext_json from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware -from kallithea.lib.compat import json from kallithea.lib.exceptions import UserCreationError from kallithea.lib.utils import get_repo_slug, is_valid_repo -from kallithea.lib.utils2 import AttributeDict, safe_int, safe_str, safe_unicode, set_hook_environment, str2bool +from kallithea.lib.utils2 import AttributeDict, ascii_bytes, safe_int, safe_str, set_hook_environment, str2bool from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError from kallithea.model import meta from kallithea.model.db import PullRequest, Repository, Setting, User @@ -97,12 +96,18 @@ return _filter_proxy(ip) -def _get_access_path(environ): - """Return PATH_INFO from environ ... using tg.original_request if available.""" +def get_path_info(environ): + """Return PATH_INFO from environ ... using tg.original_request if available. + + In Python 3 WSGI, PATH_INFO is a unicode str, but kind of contains encoded + bytes. The code points are guaranteed to only use the lower 8 bit bits, and + encoding the string with the 1:1 encoding latin1 will give the + corresponding byte string ... which then can be decoded to proper unicode. + """ org_req = environ.get('tg.original_request') if org_req is not None: environ = org_req.environ - return environ.get('PATH_INFO') + return safe_str(environ['PATH_INFO'].encode('latin1')) def log_in_user(user, remember, is_external_auth, ip_addr): @@ -172,7 +177,7 @@ (authmeth, auth) = authorization.split(' ', 1) if 'basic' != authmeth.lower(): return self.build_authentication(environ) - auth = auth.strip().decode('base64') + auth = safe_str(base64.b64decode(auth.strip())) _parts = auth.split(':', 1) if len(_parts) == 2: username, password = _parts @@ -242,7 +247,7 @@ # If not authenticated by the container, running basic auth if not username: - self.authenticate.realm = safe_str(self.config['realm']) + self.authenticate.realm = self.config['realm'] result = self.authenticate(environ) if isinstance(result, str): paste.httpheaders.AUTH_TYPE.update(environ, 'basic') @@ -300,7 +305,6 @@ return _get_ip_addr(environ) def __call__(self, environ, start_response): - start = time.time() try: # try parsing a request for this VCS - if it fails, call the wrapped app parsed_request = self.parse_request(environ) @@ -334,7 +338,7 @@ try: log.info('%s action on %s repo "%s" by "%s" from %s', - parsed_request.action, self.scm_alias, parsed_request.repo_name, safe_str(user.username), ip_addr) + parsed_request.action, self.scm_alias, parsed_request.repo_name, user.username, ip_addr) app = self._make_app(parsed_request) return app(environ, start_response) except Exception: @@ -343,10 +347,6 @@ except webob.exc.HTTPException as e: return e(environ, start_response) - finally: - log_ = logging.getLogger('kallithea.' + self.__class__.__name__) - log_.debug('Request time: %.3fs', time.time() - start) - meta.Session.remove() class BaseController(TGController): @@ -413,7 +413,7 @@ # END CONFIG VARS c.repo_name = get_repo_slug(request) # can be empty - c.backends = BACKENDS.keys() + c.backends = list(BACKENDS) self.cut_off_limit = safe_int(config.get('cut_off_limit')) @@ -531,7 +531,7 @@ log.info('IP: %s User: %s accessed %s', request.ip_addr, request.authuser, - safe_unicode(_get_access_path(environ)), + get_path_info(environ), ) return super(BaseController, self).__call__(environ, context) except webob.exc.HTTPException as e: @@ -558,7 +558,7 @@ return log.debug('Found repository in database %s with state `%s`', - safe_unicode(_dbr), safe_unicode(_dbr.repo_state)) + _dbr, _dbr.repo_state) route = getattr(request.environ.get('routes.route'), 'name', '') # allow to delete repos that are somehow damages in filesystem @@ -608,7 +608,7 @@ raise webob.exc.HTTPNotFound() except RepositoryError as e: log.error(traceback.format_exc()) - h.flash(safe_str(e), category='error') + h.flash(e, category='error') raise webob.exc.HTTPBadRequest() @@ -634,7 +634,7 @@ warnings.warn(msg, Warning, 2) log.warning(msg) log.debug("Returning JSON wrapped action output") - return json.dumps(data, encoding='utf-8') + return ascii_bytes(ext_json.dumps(data)) @decorator.decorator def IfSshEnabled(func, *args, **kwargs): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/caching_query.py --- a/kallithea/lib/caching_query.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/caching_query.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,3 +1,5 @@ +# apparently based on https://github.com/sqlalchemy/sqlalchemy/blob/rel_0_7/examples/beaker_caching/caching_query.py + """caching_query.py Represent persistence structures which allow the usage of @@ -22,8 +24,6 @@ from sqlalchemy.orm.query import Query from sqlalchemy.sql import visitors -from kallithea.lib.utils2 import safe_str - class CachingQuery(Query): """A Query subclass which optionally loads full results from a Beaker @@ -136,11 +136,10 @@ if cache_key is None: # cache key - the value arguments from this query's parameters. - args = [safe_str(x) for x in _params_from_query(query)] - args.extend(filter(lambda k: k not in ['None', None, u'None'], - [str(query._limit), str(query._offset)])) - - cache_key = " ".join(args) + args = _params_from_query(query) + args.append(query._limit) + args.append(query._offset) + cache_key = " ".join(str(x) for x in args) if cache_key is None: raise Exception('Cache key cannot be None') @@ -174,7 +173,7 @@ "for region %r namespace %r" % (region, namespace) ) - query._cache_parameters = region, safe_str(namespace), cache_key + query._cache_parameters = region, namespace, cache_key class FromCache(MapperOption): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/celerylib/__init__.py --- a/kallithea/lib/celerylib/__init__.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/celerylib/__init__.py Thu Feb 06 01:19:23 2020 +0100 @@ -35,7 +35,7 @@ from kallithea import CELERY_EAGER, CELERY_ON from kallithea.lib.pidlock import DaemonLock, LockHeld -from kallithea.lib.utils2 import safe_str +from kallithea.lib.utils2 import safe_bytes from kallithea.model import meta @@ -95,7 +95,7 @@ func_name = str(func.__name__) if hasattr(func, '__name__') else str(func) lockkey = 'task_%s.lock' % \ - md5(func_name + '-' + '-'.join(map(safe_str, params))).hexdigest() + md5(safe_bytes(func_name + '-' + '-'.join(str(x) for x in params))).hexdigest() return lockkey diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/celerylib/tasks.py --- a/kallithea/lib/celerylib/tasks.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/celerylib/tasks.py Thu Feb 06 01:19:23 2020 +0100 @@ -26,9 +26,9 @@ :license: GPLv3, see LICENSE.md for more details. """ +import email.utils import logging import os -import rfc822 import traceback from collections import OrderedDict from operator import itemgetter @@ -37,13 +37,12 @@ from tg import config from kallithea import CELERY_ON -from kallithea.lib import celerylib -from kallithea.lib.compat import json +from kallithea.lib import celerylib, ext_json from kallithea.lib.helpers import person from kallithea.lib.hooks import log_create_repository from kallithea.lib.rcmail.smtp_mailer import SmtpMailer from kallithea.lib.utils import action_logger -from kallithea.lib.utils2 import str2bool +from kallithea.lib.utils2 import ascii_bytes, str2bool from kallithea.lib.vcs.utils import author_email from kallithea.model.db import RepoGroup, Repository, Statistics, User @@ -118,22 +117,21 @@ return True if cur_stats: - commits_by_day_aggregate = OrderedDict(json.loads( + commits_by_day_aggregate = OrderedDict(ext_json.loads( cur_stats.commit_activity_combined)) - co_day_auth_aggr = json.loads(cur_stats.commit_activity) + co_day_auth_aggr = ext_json.loads(cur_stats.commit_activity) log.debug('starting parsing %s', parse_limit) - lmktime = mktime - last_rev = last_rev + 1 if last_rev >= 0 else 0 + last_rev = last_rev + 1 if last_rev and last_rev >= 0 else 0 log.debug('Getting revisions from %s to %s', last_rev, last_rev + parse_limit ) for cs in repo[last_rev:last_rev + parse_limit]: log.debug('parsing %s', cs) last_cs = cs # remember last parsed changeset - k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1], - cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0]) + tt = cs.date.timetuple() + k = mktime(tt[:3] + (0, 0, 0, 0, 0, 0)) if akc(cs.author) in co_day_auth_aggr: try: @@ -143,8 +141,7 @@ except ValueError: time_pos = None - if time_pos >= 0 and time_pos is not None: - + if time_pos is not None and time_pos >= 0: datadict = \ co_day_auth_aggr[akc(cs.author)]['data'][time_pos] @@ -195,8 +192,8 @@ } stats = cur_stats if cur_stats else Statistics() - stats.commit_activity = json.dumps(co_day_auth_aggr) - stats.commit_activity_combined = json.dumps(overview_data) + stats.commit_activity = ascii_bytes(ext_json.dumps(co_day_auth_aggr)) + stats.commit_activity_combined = ascii_bytes(ext_json.dumps(overview_data)) log.debug('last revision %s', last_rev) leftovers = len(repo.revisions[last_rev:]) @@ -204,7 +201,7 @@ if last_rev == 0 or leftovers < parse_limit: log.debug('getting code trending stats') - stats.languages = json.dumps(__get_codes_stats(repo_name)) + stats.languages = ascii_bytes(ext_json.dumps(__get_codes_stats(repo_name))) try: stats.repository = dbrepo @@ -282,7 +279,7 @@ # extract the e-mail address. envelope_addr = author_email(envelope_from) headers['From'] = '"%s" <%s>' % ( - rfc822.quote('%s (no-reply)' % author.full_name_or_username), + email.utils.quote('%s (no-reply)' % author.full_name_or_username), envelope_addr) user = email_config.get('smtp_username') @@ -489,7 +486,7 @@ for _topnode, _dirnodes, filenodes in tip.walk('/'): for filenode in filenodes: ext = filenode.extension.lower() - if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not filenode.is_binary: + if ext in LANGUAGES_EXTENSIONS_MAP and not filenode.is_binary: if ext in code_stats: code_stats[ext] += 1 else: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/celerypylons/__init__.py --- a/kallithea/lib/celerypylons/__init__.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/celerypylons/__init__.py Thu Feb 06 01:19:23 2020 +0100 @@ -39,7 +39,7 @@ celery_key = config_key.replace('.', '_').upper() if celery_key.split('_', 1)[0] not in PREFIXES: continue - if not isinstance(config_value, basestring): + if not isinstance(config_value, str): continue if celery_key in LIST_PARAMS: celery_value = config_value.split() @@ -53,6 +53,8 @@ return celery_config -# Create celery app from the TurboGears configuration file -app = celery.Celery() -app.config_from_object(celery_config(tg.config)) +def make_app(): + """Create celery app from the TurboGears configuration file""" + app = celery.Celery() + app.config_from_object(celery_config(tg.config)) + return app diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/colored_formatter.py --- a/kallithea/lib/colored_formatter.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/colored_formatter.py Thu Feb 06 01:19:23 2020 +0100 @@ -15,7 +15,7 @@ import logging -BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38) +BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30, 38) # Sequences RESET_SEQ = "\033[0m" diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/compat.py --- a/kallithea/lib/compat.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/compat.py Thu Feb 06 01:19:23 2020 +0100 @@ -29,7 +29,6 @@ import functools import os -import sys #============================================================================== # Hybrid property/method @@ -43,15 +42,10 @@ #============================================================================== # json #============================================================================== -from kallithea.lib.ext_json import json +from kallithea.lib import ext_json -# alias for formatted json -formatted_json = functools.partial(json.dumps, indent=4, sort_keys=True) - - - - +formatted_json = functools.partial(ext_json.dumps, indent=4, sort_keys=True) #============================================================================== diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/db_manage.py --- a/kallithea/lib/db_manage.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/db_manage.py Thu Feb 06 01:19:23 2020 +0100 @@ -189,7 +189,7 @@ return password if username is None: - username = raw_input('Specify admin username:') + username = input('Specify admin username:') if password is None: password = get_password() if not password: @@ -198,7 +198,7 @@ if not password: sys.exit() if email is None: - email = raw_input('Specify admin email:') + email = input('Specify admin email:') self.create_user(username, password, email, True) else: log.info('creating admin and regular test users') @@ -294,7 +294,7 @@ if _path is not None: path = _path elif not self.tests and not test_repo_path: - path = raw_input( + path = input( 'Enter a valid absolute path to store repositories. ' 'All repositories in that path will be added automatically:' ) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/diffs.py --- a/kallithea/lib/diffs.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/diffs.py Thu Feb 06 01:19:23 2020 +0100 @@ -32,7 +32,7 @@ from tg.i18n import ugettext as _ from kallithea.lib import helpers as h -from kallithea.lib.utils2 import safe_unicode +from kallithea.lib.utils2 import safe_str from kallithea.lib.vcs.backends.base import EmptyChangeset from kallithea.lib.vcs.exceptions import VCSError from kallithea.lib.vcs.nodes import FileNode, SubModuleNode @@ -216,8 +216,7 @@ stats = (0, 0) if not html_diff: - submodules = filter(lambda o: isinstance(o, SubModuleNode), - [filenode_new, filenode_old]) + submodules = [o for o in [filenode_new, filenode_old] if isinstance(o, SubModuleNode)] if submodules: html_diff = wrap_to_table(h.escape('Submodule %r' % submodules[0])) else: @@ -235,10 +234,9 @@ """ # make sure we pass in default context context = context or 3 - submodules = filter(lambda o: isinstance(o, SubModuleNode), - [filenode_new, filenode_old]) + submodules = [o for o in [filenode_new, filenode_old] if isinstance(o, SubModuleNode)] if submodules: - return '' + return b'' for filenode in (filenode_old, filenode_new): if not isinstance(filenode, FileNode): @@ -263,7 +261,7 @@ ignore_whitespace=ignore_whitespace, context=context) except MemoryError: h.flash('MemoryError: Diff is too big', category='error') - return '' + return b'' NEW_FILENODE = 1 @@ -281,7 +279,7 @@ mentioned in the diff together with a dict of meta information that can be used to render it in a HTML template. """ - _diff_git_re = re.compile('^diff --git', re.MULTILINE) + _diff_git_re = re.compile(b'^diff --git', re.MULTILINE) def __init__(self, diff, vcs='hg', diff_limit=None, inline_diff=True): """ @@ -291,10 +289,10 @@ based on that parameter cut off will be triggered, set to None to show full diff """ - if not isinstance(diff, basestring): - raise Exception('Diff must be a basestring got %s instead' % type(diff)) + if not isinstance(diff, bytes): + raise Exception('Diff must be bytes - got %s' % type(diff)) - self._diff = diff + self._diff = memoryview(diff) self.adds = 0 self.removes = 0 self.diff_limit = diff_limit @@ -317,7 +315,7 @@ self.limited_diff = True continue - head, diff_lines = _get_header(self.vcs, buffer(self._diff, start, end - start)) + head, diff_lines = _get_header(self.vcs, self._diff[start:end]) op = None stats = { @@ -399,7 +397,7 @@ 'new_lineno': '', 'action': 'context', 'line': msg, - } for _op, msg in stats['ops'].iteritems() + } for _op, msg in stats['ops'].items() if _op not in [MOD_FILENODE]]) _files.append({ @@ -420,22 +418,22 @@ for chunk in diff_data['chunks']: lineiter = iter(chunk) try: - peekline = lineiter.next() + peekline = next(lineiter) while True: # find a first del line while peekline['action'] != 'del': - peekline = lineiter.next() + peekline = next(lineiter) delline = peekline - peekline = lineiter.next() + peekline = next(lineiter) # if not followed by add, eat all following del lines if peekline['action'] != 'add': while peekline['action'] == 'del': - peekline = lineiter.next() + peekline = next(lineiter) continue # found an add - make sure it is the only one addline = peekline try: - peekline = lineiter.next() + peekline = next(lineiter) except StopIteration: # add was last line - ok _highlight_inline_diff(delline, addline) @@ -479,10 +477,10 @@ return ' ' assert False - return _escape_re.sub(substitute, safe_unicode(string)) + return _escape_re.sub(substitute, safe_str(string)) -_git_header_re = re.compile(r""" +_git_header_re = re.compile(br""" ^diff[ ]--git[ ]a/(?P.+?)[ ]b/(?P.+?)\n (?:^old[ ]mode[ ](?P\d+)\n ^new[ ]mode[ ](?P\d+)(?:\n|$))? @@ -499,7 +497,7 @@ """, re.VERBOSE | re.MULTILINE) -_hg_header_re = re.compile(r""" +_hg_header_re = re.compile(br""" ^diff[ ]--git[ ]a/(?P.+?)[ ]b/(?P.+?)\n (?:^old[ ]mode[ ](?P\d+)\n ^new[ ]mode[ ](?P\d+)(?:\n|$))? @@ -518,6 +516,9 @@ """, re.VERBOSE | re.MULTILINE) +_header_next_check = re.compile(br'''(?!@)(?!literal )(?!delta )''') + + def _get_header(vcs, diff_chunk): """ Parses a Git diff for a single file (header and chunks) and returns a tuple with: @@ -537,11 +538,11 @@ match = _hg_header_re.match(diff_chunk) if match is None: raise Exception('diff not recognized as valid %s diff' % vcs) - meta_info = match.groupdict() + meta_info = {k: None if v is None else safe_str(v) for k, v in match.groupdict().items()} rest = diff_chunk[match.end():] - if rest and not rest.startswith('@') and not rest.startswith('literal ') and not rest.startswith('delta '): - raise Exception('cannot parse %s diff header: %r followed by %r' % (vcs, diff_chunk[:match.end()], rest[:1000])) - diff_lines = (_escaper(m.group(0)) for m in re.finditer(r'.*\n|.+$', rest)) # don't split on \r as str.splitlines do + if rest and _header_next_check.match(rest): + raise Exception('cannot parse %s diff header: %r followed by %r' % (vcs, safe_str(bytes(diff_chunk[:match.end()])), safe_str(bytes(rest[:1000])))) + diff_lines = (_escaper(m.group(0)) for m in re.finditer(br'.*\n|.+$', rest)) # don't split on \r as str.splitlines do return meta_info, diff_lines @@ -557,9 +558,9 @@ added = deleted = 0 old_line = old_end = new_line = new_end = None + chunks = [] try: - chunks = [] - line = diff_lines.next() + line = next(diff_lines) while True: lines = [] @@ -590,7 +591,7 @@ 'line': line, }) - line = diff_lines.next() + line = next(diff_lines) while old_line < old_end or new_line < new_end: if not line: @@ -623,7 +624,7 @@ 'line': line[1:], }) - line = diff_lines.next() + line = next(diff_lines) if _newline_marker.match(line): # we need to append to lines, since this is not @@ -634,7 +635,7 @@ 'action': 'context', 'line': line, }) - line = diff_lines.next() + line = next(diff_lines) if old_line > old_end: raise Exception('error parsing diff - more than %s "-" lines at -%s+%s' % (old_end, old_line, new_line)) if new_line > new_end: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/ext_json.py --- a/kallithea/lib/ext_json.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/ext_json.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,16 +1,16 @@ """ -Extended JSON encoder for json +Extended JSON encoder with support for more data types -json.org does not specify how date time can be represented - monkeypatch it to do something. +json.org does not specify how date time can be represented - just encode it somehow and ignore decoding ... """ import datetime import decimal import functools -import json # is re-exported after monkey patching +import json -__all__ = ['json'] +__all__ = ['dumps', 'dump', 'load', 'loads'] def _is_tz_aware(value): @@ -70,10 +70,12 @@ try: return _obj_dump(obj) except NotImplementedError: - pass + pass # quiet skipping of unsupported types! raise TypeError("%r is not JSON serializable" % (obj,)) -# monkey-patch and export JSON encoder to use custom encoding method -json.dumps = functools.partial(json.dumps, cls=ExtendedEncoder) -json.dump = functools.partial(json.dump, cls=ExtendedEncoder) +dumps = functools.partial(json.dumps, cls=ExtendedEncoder) +dump = functools.partial(json.dump, cls=ExtendedEncoder) +# No special support for loading these types back!!! +load = json.load +loads = json.loads diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/feeds.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/lib/feeds.py Thu Feb 06 01:19:23 2020 +0100 @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +kallithea.lib.feeds +~~~~~~~~~~~~~~~~~~~ + +Shared code for providing RSS and ATOM feeds. +""" + +import datetime +import re + +import mako.template + + +language = 'en-us' +ttl = "5" + + +# From ``django.utils.feedgenerator`` via webhelpers.feedgenerator +def rfc2822_date(date): + # We do this ourselves to be timezone aware, email.Utils is not tz aware. + if getattr(date, "tzinfo", False): + time_str = date.strftime('%a, %d %b %Y %H:%M:%S ') + offset = date.tzinfo.utcoffset(date) + timezone = (offset.days * 24 * 60) + (offset.seconds / 60) + hour, minute = divmod(timezone, 60) + return time_str + "%+03d%02d" % (hour, minute) + else: + return date.strftime('%a, %d %b %Y %H:%M:%S -0000') + +# From ``django.utils.feedgenerator`` via webhelpers.feedgenerator +def rfc3339_date(date): + if getattr(date, "tzinfo", False): + time_str = date.strftime('%Y-%m-%dT%H:%M:%S') + offset = date.tzinfo.utcoffset(date) + timezone = (offset.days * 24 * 60) + (offset.seconds / 60) + hour, minute = divmod(timezone, 60) + return time_str + "%+03d:%02d" % (hour, minute) + else: + return date.strftime('%Y-%m-%dT%H:%M:%SZ') + +# From ``django.utils.feedgenerator`` via webhelpers.feedgenerator +def get_tag_uri(url, date): + "Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id" + tag = re.sub('^http://', '', url) + if date is not None: + tag = re.sub('/', ',%s:/' % date.strftime('%Y-%m-%d'), tag, 1) + tag = re.sub('#', '/', tag) + return u'tag:' + tag + + +class Attributes(object): + """Simple namespace for attribute dict access in mako and elsewhere""" + def __init__(self, a_dict): + self.__dict__ = a_dict + + +class _Feeder(object): + + content_type = None + template = None # subclass must provide a mako.template.Template + + @classmethod + def render(cls, header, entries): + try: + latest_pubdate = max( + pubdate for pubdate in (e.get('pubdate') for e in entries) + if pubdate + ) + except ValueError: # max() arg is an empty sequence ... or worse + latest_pubdate = datetime.datetime.now() + + return cls.template.render( + language=language, + ttl=ttl, # rss only + latest_pubdate=latest_pubdate, + rfc2822_date=rfc2822_date, # for RSS + rfc3339_date=rfc3339_date, # for Atom + get_tag_uri=get_tag_uri, + entries=[Attributes(e) for e in entries], + **header + ) + + +class AtomFeed(_Feeder): + + content_type = 'application/atom+xml' + + template = mako.template.Template('''\ + + + ${title} + + ${link} + ${rfc3339_date(latest_pubdate)} + % for entry in entries: + + ${entry.title} + + ${rfc3339_date(entry.pubdate)} + ${rfc3339_date(entry.pubdate)} + + ${entry.author_name} + ${entry.author_email} + + ${get_tag_uri(entry.link, entry.pubdate)} + ${entry.description} + + % endfor + +''', default_filters=['x'], output_encoding='utf-8', encoding_errors='replace') + + +class RssFeed(_Feeder): + + content_type = 'application/rss+xml' + + template = mako.template.Template('''\ + + + + ${title} + ${link} + ${description} + ${language} + ${rfc2822_date(latest_pubdate)} + ${ttl} + % for entry in entries: + + ${entry.title} + ${entry.link} + ${entry.description} + ${entry.author_email} (${entry.author_name}) + ${rfc2822_date(entry.pubdate)} + + % endfor + + +''', default_filters=['x'], output_encoding='utf-8', encoding_errors='replace') diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/helpers.py --- a/kallithea/lib/helpers.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/helpers.py Thu Feb 06 01:19:23 2020 +0100 @@ -22,9 +22,8 @@ import logging import random import re -import StringIO import textwrap -import urlparse +import urllib.parse from beaker.cache import cache_region from pygments import highlight as code_highlight @@ -49,7 +48,7 @@ from kallithea.lib.pygmentsutils import get_custom_lexer from kallithea.lib.utils2 import MENTIONS_REGEX, AttributeDict from kallithea.lib.utils2 import age as _age -from kallithea.lib.utils2 import credentials_filter, safe_int, safe_str, safe_unicode, str2bool, time_to_datetime +from kallithea.lib.utils2 import credentials_filter, safe_bytes, safe_int, safe_str, str2bool, time_to_datetime from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError #============================================================================== @@ -167,7 +166,7 @@ for x in option_list: if isinstance(x, tuple) and len(x) == 2: value, label = x - elif isinstance(x, basestring): + elif isinstance(x, str): value = label = x else: log.error('invalid select option %r', x) @@ -177,7 +176,7 @@ for x in value: if isinstance(x, tuple) and len(x) == 2: group_value, group_label = x - elif isinstance(x, basestring): + elif isinstance(x, str): group_value = group_label = x else: log.error('invalid select option %r', x) @@ -200,14 +199,12 @@ :param path: """ - return 'C-%s-%s' % (short_id(raw_id), hashlib.md5(safe_str(path)).hexdigest()[:12]) + return 'C-%s-%s' % (short_id(raw_id), hashlib.md5(safe_bytes(path)).hexdigest()[:12]) class _FilesBreadCrumbs(object): def __call__(self, repo_name, rev, paths): - if isinstance(paths, str): - paths = safe_unicode(paths) url_l = [link_to(repo_name, url('files_home', repo_name=repo_name, revision=rev, f_path=''), @@ -246,12 +243,12 @@ yield i, t def _wrap_tablelinenos(self, inner): - dummyoutfile = StringIO.StringIO() + inner_lines = [] lncount = 0 for t, line in inner: if t: lncount += 1 - dummyoutfile.write(line) + inner_lines.append(line) fl = self.linenostart mw = len(str(lncount + fl - 1)) @@ -304,7 +301,7 @@ '
' '
' + ls + '
' '') - yield 0, dummyoutfile.getvalue() + yield 0, ''.join(inner_lines) yield 0, '' @@ -331,7 +328,48 @@ """ lexer = get_custom_lexer(filenode.extension) or filenode.lexer return literal(markup_whitespace( - code_highlight(filenode.content, lexer, CodeHtmlFormatter(**kwargs)))) + code_highlight(safe_str(filenode.content), lexer, CodeHtmlFormatter(**kwargs)))) + + +def hsv_to_rgb(h, s, v): + if s == 0.0: + return v, v, v + i = int(h * 6.0) # XXX assume int() truncates! + f = (h * 6.0) - i + p = v * (1.0 - s) + q = v * (1.0 - s * f) + t = v * (1.0 - s * (1.0 - f)) + i = i % 6 + if i == 0: + return v, t, p + if i == 1: + return q, v, p + if i == 2: + return p, v, t + if i == 3: + return p, q, v + if i == 4: + return t, p, v + if i == 5: + return v, p, q + + +def gen_color(n=10000): + """generator for getting n of evenly distributed colors using + hsv color and golden ratio. It always return same order of colors + + :returns: RGB tuple + """ + + golden_ratio = 0.618033988749895 + h = 0.22717784590367374 + + for _unused in range(n): + h += golden_ratio + h %= 1 + HSV_tuple = [h, 0.95, 0.95] + RGB_tuple = hsv_to_rgb(*HSV_tuple) + yield [str(int(x * 256)) for x in RGB_tuple] def pygmentize_annotation(repo_name, filenode, **kwargs): @@ -340,82 +378,38 @@ :param filenode: """ - + cgenerator = gen_color() color_dict = {} - def gen_color(n=10000): - """generator for getting n of evenly distributed colors using - hsv color and golden ratio. It always return same order of colors - - :returns: RGB tuple - """ - - def hsv_to_rgb(h, s, v): - if s == 0.0: - return v, v, v - i = int(h * 6.0) # XXX assume int() truncates! - f = (h * 6.0) - i - p = v * (1.0 - s) - q = v * (1.0 - s * f) - t = v * (1.0 - s * (1.0 - f)) - i = i % 6 - if i == 0: - return v, t, p - if i == 1: - return q, v, p - if i == 2: - return p, v, t - if i == 3: - return p, q, v - if i == 4: - return t, p, v - if i == 5: - return v, p, q - - golden_ratio = 0.618033988749895 - h = 0.22717784590367374 - - for _unused in xrange(n): - h += golden_ratio - h %= 1 - HSV_tuple = [h, 0.95, 0.95] - RGB_tuple = hsv_to_rgb(*HSV_tuple) - yield map(lambda x: str(int(x * 256)), RGB_tuple) - - cgenerator = gen_color() - def get_color_string(cs): if cs in color_dict: col = color_dict[cs] else: - col = color_dict[cs] = cgenerator.next() + col = color_dict[cs] = next(cgenerator) return "color: rgb(%s)! important;" % (', '.join(col)) - def url_func(repo_name): - - def _url_func(changeset): - author = escape(changeset.author) - date = changeset.date - message = escape(changeset.message) - tooltip_html = ("Author: %s
" - "Date: %s
" - "Message: %s") % (author, date, message) + def url_func(changeset): + author = escape(changeset.author) + date = changeset.date + message = escape(changeset.message) + tooltip_html = ("Author: %s
" + "Date: %s
" + "Message: %s") % (author, date, message) - lnk_format = show_id(changeset) - uri = link_to( - lnk_format, - url('changeset_home', repo_name=repo_name, - revision=changeset.raw_id), - style=get_color_string(changeset.raw_id), - **{'data-toggle': 'popover', - 'data-content': tooltip_html} - ) + lnk_format = show_id(changeset) + uri = link_to( + lnk_format, + url('changeset_home', repo_name=repo_name, + revision=changeset.raw_id), + style=get_color_string(changeset.raw_id), + **{'data-toggle': 'popover', + 'data-content': tooltip_html} + ) - uri += '\n' - return uri - return _url_func + uri += '\n' + return uri - return literal(markup_whitespace(annotate_highlight(filenode, url_func(repo_name), **kwargs))) + return literal(markup_whitespace(annotate_highlight(filenode, url_func, **kwargs))) class _Message(object): @@ -424,22 +418,14 @@ Converting the message to a string returns the message text. Instances also have the following attributes: - * ``message``: the message text. * ``category``: the category specified when the message was created. + * ``message``: the html-safe message text. """ def __init__(self, category, message): self.category = category self.message = message - def __str__(self): - return self.message - - __unicode__ = __str__ - - def __html__(self): - return escape(safe_unicode(self.message)) - def _session_flash_messages(append=None, clear=False): """Manage a message queue in tg.session: return the current message queue @@ -461,7 +447,7 @@ return flash_messages -def flash(message, category=None, logf=None): +def flash(message, category, logf=None): """ Show a message to the user _and_ log it through the specified function @@ -471,14 +457,22 @@ logf defaults to log.info, unless category equals 'success', in which case logf defaults to log.debug. """ + assert category in ('error', 'success', 'warning'), category + if hasattr(message, '__html__'): + # render to HTML for storing in cookie + safe_message = str(message) + else: + # Apply str - the message might be an exception with __str__ + # Escape, so we can trust the result without further escaping, without any risk of injection + safe_message = html_escape(str(message)) if logf is None: logf = log.info if category == 'success': logf = log.debug - logf('Flash %s: %s', category, message) + logf('Flash %s: %s', category, safe_message) - _session_flash_messages(append=(category, message)) + _session_flash_messages(append=(category, safe_message)) def pop_flash_messages(): @@ -486,7 +480,7 @@ The return value is a list of ``Message`` objects. """ - return [_Message(*m) for m in _session_flash_messages(clear=True)] + return [_Message(category, message) for category, message in _session_flash_messages(clear=True)] age = lambda x, y=False: _age(x, y) @@ -516,8 +510,7 @@ def fmt_date(date): if date: - return date.strftime("%Y-%m-%d %H:%M:%S").decode('utf-8') - + return date.strftime("%Y-%m-%d %H:%M:%S") return "" @@ -677,7 +670,7 @@ return _op, _name revs = [] - if len(filter(lambda v: v != '', revs_ids)) > 0: + if len([v for v in revs_ids if v != '']) > 0: repo = None for rev in revs_ids[:revs_top_limit]: _op, _name = _get_op(rev) @@ -937,13 +930,13 @@ if email_address == _def: return default - parsed_url = urlparse.urlparse(url.current(qualified=True)) + parsed_url = urllib.parse.urlparse(url.current(qualified=True)) url = (c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL) \ .replace('{email}', email_address) \ - .replace('{md5email}', hashlib.md5(safe_str(email_address).lower()).hexdigest()) \ + .replace('{md5email}', hashlib.md5(safe_bytes(email_address).lower()).hexdigest()) \ .replace('{netloc}', parsed_url.netloc) \ .replace('{scheme}', parsed_url.scheme) \ - .replace('{size}', safe_str(size)) + .replace('{size}', str(size)) return url @@ -959,7 +952,7 @@ suf = '' if len(nodes) > 30: suf = '
' + _(' and %s more') % (len(nodes) - 30) - return literal(pref + '
'.join([safe_unicode(x.path) + return literal(pref + '
'.join([x.path for x in nodes[:30]]) + suf) else: return ': ' + _('No files') @@ -1165,7 +1158,7 @@ tmp_urlify_issues_f = lambda s: s issue_pat_re = re.compile(r'issue_pat(.*)') - for k in CONFIG.keys(): + for k in CONFIG: # Find all issue_pat* settings that also have corresponding server_link and prefix configuration m = issue_pat_re.match(k) if m is None: @@ -1229,7 +1222,7 @@ Render plain text with revision hashes and issue references urlified and with @mention highlighting. """ - s = safe_unicode(source) + s = safe_str(source) s = urlify_text(s, repo_name=repo_name) return literal('
%s
' % s) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/hooks.py --- a/kallithea/lib/hooks.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/hooks.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,16 +25,17 @@ :license: GPLv3, see LICENSE.md for more details. """ -import binascii import os +import sys import time +import mercurial.scmutil + from kallithea.lib import helpers as h from kallithea.lib.exceptions import UserCreationError -from kallithea.lib.utils import action_logger, make_ui, setup_cache_regions -from kallithea.lib.utils2 import get_hook_environment, safe_str, safe_unicode +from kallithea.lib.utils import action_logger, make_ui +from kallithea.lib.utils2 import HookEnvironmentError, ascii_str, get_hook_environment, safe_bytes, safe_str from kallithea.lib.vcs.backends.base import EmptyChangeset -from kallithea.lib.vcs.utils.hgcompat import revrange from kallithea.model.db import Repository, User @@ -43,7 +44,7 @@ alias += '.' size_scm, size_root = 0, 0 - for path, dirs, files in os.walk(safe_str(root_path)): + for path, dirs, files in os.walk(root_path): if path.find(alias) != -1: for f in files: try: @@ -65,16 +66,16 @@ def repo_size(ui, repo, hooktype=None, **kwargs): - """Presents size of repository after push""" - size_hg_f, size_root_f, size_total_f = _get_scm_size('.hg', repo.root) + """Show size of Mercurial repository, to be called after push.""" + size_hg_f, size_root_f, size_total_f = _get_scm_size('.hg', safe_str(repo.root)) last_cs = repo[len(repo) - 1] msg = ('Repository size .hg: %s Checkout: %s Total: %s\n' 'Last revision is now r%s:%s\n') % ( - size_hg_f, size_root_f, size_total_f, last_cs.rev(), last_cs.hex()[:12] + size_hg_f, size_root_f, size_total_f, last_cs.rev(), ascii_str(last_cs.hex())[:12] ) - ui.status(msg) + ui.status(safe_bytes(msg)) def log_pull_action(ui, repo, **kwargs): @@ -109,8 +110,7 @@ Note: This hook is not only logging, but also the side effect invalidating cahes! The function should perhaps be renamed. """ - _h = binascii.hexlify - revs = [_h(repo[r].node()) for r in revrange(repo, [node + ':' + node_last])] + revs = [ascii_str(repo[r].hex()) for r in mercurial.scmutil.revrange(repo, [b'%s:%s' % (node, node_last)])] process_pushed_raw_ids(revs) return 0 @@ -302,31 +302,23 @@ they thus need enough info to be able to create an app environment and connect to the database. """ - from paste.deploy import appconfig - from sqlalchemy import engine_from_config - from kallithea.config.environment import load_environment - from kallithea.model.base import init_model + import paste.deploy + import kallithea.config.middleware extras = get_hook_environment() - ini_file_path = extras['config'] - #logging.config.fileConfig(ini_file_path) # Note: we are in a different process - don't use configured logging - app_conf = appconfig('config:%s' % ini_file_path) - conf = load_environment(app_conf.global_conf, app_conf.local_conf) - setup_cache_regions(conf) + path_to_ini_file = extras['config'] + kallithea.CONFIG = paste.deploy.appconfig('config:' + path_to_ini_file) + #logging.config.fileConfig(ini_file_path) # Note: we are in a different process - don't use configured logging + kallithea.config.middleware.make_app(kallithea.CONFIG.global_conf, **kallithea.CONFIG.local_conf) - engine = engine_from_config(conf, 'sqlalchemy.') - init_model(engine) - - repo_path = safe_unicode(repo_path) # fix if it's not a bare repo if repo_path.endswith(os.sep + '.git'): repo_path = repo_path[:-5] repo = Repository.get_by_full_path(repo_path) if not repo: - raise OSError('Repository %s not found in database' - % (safe_str(repo_path))) + raise OSError('Repository %s not found in database' % repo_path) baseui = make_ui() return baseui, repo @@ -340,7 +332,11 @@ def handle_git_post_receive(repo_path, git_stdin_lines): """Called from Git post-receive hook""" - baseui, repo = _hook_environment(repo_path) + try: + baseui, repo = _hook_environment(repo_path) + except HookEnvironmentError as e: + sys.stderr.write("Skipping Kallithea Git post-recieve hook %r.\nGit was apparently not invoked by Kallithea: %s\n" % (sys.argv[0], e)) + return 0 # the post push hook should never use the cached instance scm_repo = repo.scm_instance_no_cache() @@ -363,19 +359,20 @@ if push_ref['old_rev'] == EmptyChangeset().raw_id: # update the symbolic ref if we push new repo if scm_repo.is_empty(): - scm_repo._repo.refs.set_symbolic_ref('HEAD', - 'refs/heads/%s' % push_ref['name']) + scm_repo._repo.refs.set_symbolic_ref( + b'HEAD', + b'refs/heads/%s' % safe_bytes(push_ref['name'])) # build exclude list without the ref cmd = ['for-each-ref', '--format=%(refname)', 'refs/heads/*'] - stdout, stderr = scm_repo.run_git_command(cmd) + stdout = scm_repo.run_git_command(cmd) ref = push_ref['ref'] heads = [head for head in stdout.splitlines() if head != ref] # now list the git revs while excluding from the list cmd = ['log', push_ref['new_rev'], '--reverse', '--pretty=format:%H'] cmd.append('--not') cmd.extend(heads) # empty list is ok - stdout, stderr = scm_repo.run_git_command(cmd) + stdout = scm_repo.run_git_command(cmd) git_revs += stdout.splitlines() elif push_ref['new_rev'] == EmptyChangeset().raw_id: @@ -384,7 +381,7 @@ else: cmd = ['log', '%(old_rev)s..%(new_rev)s' % push_ref, '--reverse', '--pretty=format:%H'] - stdout, stderr = scm_repo.run_git_command(cmd) + stdout = scm_repo.run_git_command(cmd) git_revs += stdout.splitlines() elif _type == 'tags': @@ -399,5 +396,5 @@ def rejectpush(ui, **kwargs): """Mercurial hook to be installed as pretxnopen and prepushkey for read-only repos""" ex = get_hook_environment() - ui.warn((b"Push access to %r denied\n") % safe_str(ex.repository)) + ui.warn(safe_bytes("Push access to %r denied\n" % ex.repository)) return 1 diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/indexers/__init__.py --- a/kallithea/lib/indexers/__init__.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/indexers/__init__.py Thu Feb 06 01:19:23 2020 +0100 @@ -146,7 +146,7 @@ docnum = self.matcher.id() chunks = [offsets for offsets in self.get_chunks()] docs_id.append([docnum, chunks]) - self.matcher.next() + self.matcher.next() # this looks like a py2 iterator ... but it isn't return docs_id def __str__(self): @@ -203,8 +203,7 @@ return res def get_short_content(self, res, chunks): - - return ''.join([res['content'][chunk[0]:chunk[1]] for chunk in chunks]) + return u''.join([res['content'][chunk[0]:chunk[1]] for chunk in chunks]) def get_chunks(self): """ @@ -213,7 +212,11 @@ close occurrences twice. """ memory = [(0, 0)] - if self.matcher.supports('positions'): + try: + supports_positions = self.matcher.supports('positions') + except AttributeError: # 'NoneType' object has no attribute 'supports' (because matcher never get a format) + supports_positions = False + if supports_positions: for span in self.matcher.spans(): start = span.startchar or 0 end = span.endchar or 0 diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/indexers/daemon.py --- a/kallithea/lib/indexers/daemon.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/indexers/daemon.py Thu Feb 06 01:19:23 2020 +0100 @@ -39,7 +39,7 @@ from kallithea.config.conf import INDEX_EXTENSIONS, INDEX_FILENAMES from kallithea.lib.indexers import CHGSET_IDX_NAME, CHGSETS_SCHEMA, IDX_NAME, SCHEMA -from kallithea.lib.utils2 import safe_str, safe_unicode +from kallithea.lib.utils2 import safe_str from kallithea.lib.vcs.exceptions import ChangesetError, NodeDoesNotExistError, RepositoryError from kallithea.model.db import Repository from kallithea.model.scm import ScmModel @@ -77,8 +77,7 @@ # filter repo list if repo_list: - # Fix non-ascii repo names to unicode - repo_list = map(safe_unicode, repo_list) + repo_list = set(repo_list) self.filtered_repo_paths = {} for repo_name, repo in self.repo_paths.items(): if repo_name in repo_list: @@ -110,7 +109,7 @@ self.initial = False def _get_index_revision(self, repo): - db_repo = Repository.get_by_repo_name(repo.name_unicode) + db_repo = Repository.get_by_repo_name(repo.name) landing_rev = 'tip' if db_repo: _rev_type, _rev = db_repo.landing_rev @@ -133,7 +132,7 @@ cs = self._get_index_changeset(repo) for _topnode, _dirs, files in cs.walk('/'): for f in files: - index_paths_.add(os.path.join(safe_str(repo.path), safe_str(f.path))) + index_paths_.add(os.path.join(repo.path, f.path)) except RepositoryError: log.debug(traceback.format_exc()) @@ -142,19 +141,16 @@ def get_node(self, repo, path, index_rev=None): """ - gets a filenode based on given full path. It operates on string for - hg git compatibility. + gets a filenode based on given full path. :param repo: scm repo instance :param path: full path including root location :return: FileNode """ # FIXME: paths should be normalized ... or even better: don't include repo.path - path = safe_str(path) - repo_path = safe_str(repo.path) - assert path.startswith(repo_path) - assert path[len(repo_path)] in (os.path.sep, os.path.altsep) - node_path = path[len(repo_path) + 1:] + assert path.startswith(repo.path) + assert path[len(repo.path)] in (os.path.sep, os.path.altsep) + node_path = path[len(repo.path) + 1:] cs = self._get_index_changeset(repo, index_rev=index_rev) node = cs.get_node(node_path) return node @@ -182,12 +178,13 @@ indexed = indexed_w_content = 0 if self.is_indexable_node(node): - u_content = node.content - if not isinstance(u_content, unicode): + bytes_content = node.content + if b'\0' in bytes_content: log.warning(' >> %s - no text content', path) u_content = u'' else: log.debug(' >> %s', path) + u_content = safe_str(bytes_content) indexed_w_content += 1 else: @@ -196,13 +193,12 @@ u_content = u'' indexed += 1 - p = safe_unicode(path) writer.add_document( - fileid=p, - owner=unicode(repo.contact), - repository_rawname=safe_unicode(repo_name), - repository=safe_unicode(repo_name), - path=p, + fileid=path, + owner=repo.contact, + repository_rawname=repo_name, + repository=repo_name, + path=path, content=u_content, modtime=self.get_node_mtime(node), extension=node.extension @@ -237,18 +233,18 @@ indexed += 1 log.debug(' >> %s %s/%s', cs, indexed, total) writer.add_document( - raw_id=unicode(cs.raw_id), - owner=unicode(repo.contact), + raw_id=cs.raw_id, + owner=repo.contact, date=cs._timestamp, - repository_rawname=safe_unicode(repo_name), - repository=safe_unicode(repo_name), + repository_rawname=repo_name, + repository=repo_name, author=cs.author, message=cs.message, last=cs.last, - added=u' '.join([safe_unicode(node.path) for node in cs.added]).lower(), - removed=u' '.join([safe_unicode(node.path) for node in cs.removed]).lower(), - changed=u' '.join([safe_unicode(node.path) for node in cs.changed]).lower(), - parents=u' '.join([cs.raw_id for cs in cs.parents]), + added=u' '.join(node.path for node in cs.added).lower(), + removed=u' '.join(node.path for node in cs.removed).lower(), + changed=u' '.join(node.path for node in cs.changed).lower(), + parents=u' '.join(cs.raw_id for cs in cs.parents), ) return indexed @@ -330,8 +326,8 @@ log.debug('>> NOTHING TO COMMIT TO CHANGESET INDEX<<') def update_file_index(self): - log.debug((u'STARTING INCREMENTAL INDEXING UPDATE FOR EXTENSIONS %s ' - 'AND REPOS %s') % (INDEX_EXTENSIONS, self.repo_paths.keys())) + log.debug(u'STARTING INCREMENTAL INDEXING UPDATE FOR EXTENSIONS %s ' + 'AND REPOS %s', INDEX_EXTENSIONS, ' and '.join(self.repo_paths)) idx = open_dir(self.index_location, indexname=self.indexname) # The set of all paths in the index @@ -390,9 +386,7 @@ ri_cnt = 0 # indexed riwc_cnt = 0 # indexed with content for path in self.get_paths(repo): - path = safe_unicode(path) if path in to_index or path not in indexed_paths: - # This is either a file that's changed, or a new file # that wasn't indexed before. So index it! i, iwc = self.add_doc(writer, path, repo, repo_name) @@ -431,7 +425,7 @@ file_idx = create_in(self.index_location, SCHEMA, indexname=IDX_NAME) file_idx_writer = file_idx.writer() log.debug('BUILDING INDEX FOR EXTENSIONS %s ' - 'AND REPOS %s' % (INDEX_EXTENSIONS, self.repo_paths.keys())) + 'AND REPOS %s', INDEX_EXTENSIONS, ' and '.join(self.repo_paths)) for repo_name, repo in sorted(self.repo_paths.items()): log.debug('Updating indices for repo %s', repo_name) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/inifile.py --- a/kallithea/lib/inifile.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/inifile.py Thu Feb 06 01:19:23 2020 +0100 @@ -72,7 +72,7 @@ ... '[third-section]': {'third_extra': ' 3'}, ... '[fourth-section]': {'fourth_extra': '4', 'fourth': '"four"'}, ... } - >>> print expand(template, mako_variable_values, settings) + >>> print(expand(template, mako_variable_values, settings)) [first-section] diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/markup_renderer.py --- a/kallithea/lib/markup_renderer.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/markup_renderer.py Thu Feb 06 01:19:23 2020 +0100 @@ -33,7 +33,7 @@ import bleach import markdown as markdown_mod -from kallithea.lib.utils2 import MENTIONS_REGEX, safe_unicode +from kallithea.lib.utils2 import MENTIONS_REGEX, safe_str log = logging.getLogger(__name__) @@ -119,17 +119,17 @@ At last it will just do a simple html replacing new lines with
>>> MarkupRenderer.render('''''', '.md') - u'

' + '

' >>> MarkupRenderer.render('''''', 'b.mkd') - u'

' + '

' >>> MarkupRenderer.render('''foo''', 'c.mkdn') - u'

foo

' + '

foo

' >>> MarkupRenderer.render('''''', 'd.mdown') - u'<script>alert(1)</script>' + '<script>alert(1)</script>' >>> MarkupRenderer.render('''
yo
''', 'markdown') - u'
yo
' + '
yo
' >>> MarkupRenderer.render('''yo''', 'md') - u'

yo

' + '

yo

' """ renderer = cls._detect_renderer(source, filename) @@ -150,7 +150,7 @@ @classmethod def plain(cls, source, universal_newline=True): - source = safe_unicode(source) + source = safe_str(source) if universal_newline: newline = '\n' source = newline.join(source.splitlines()) @@ -168,30 +168,30 @@ with "safe" fall-back to plaintext. Output from this method should be sanitized before use. >>> MarkupRenderer.markdown('''''') - u'

' + '

' >>> MarkupRenderer.markdown('''''') - u'

' + '

' >>> MarkupRenderer.markdown('''foo''') - u'

foo

' + '

foo

' >>> MarkupRenderer.markdown('''''') - u'' + '' >>> MarkupRenderer.markdown('''
yo
''') - u'
yo
' + '
yo
' >>> MarkupRenderer.markdown('''yo''') - u'

yo

' + '

yo

' >>> MarkupRenderer.markdown('''## Foo''') - u'

Foo

' - >>> print MarkupRenderer.markdown(''' + '

Foo

' + >>> print(MarkupRenderer.markdown(''' ... #!/bin/bash ... echo "hello" - ... ''') + ... '''))
1
         2
#!/bin/bash
         echo "hello"
         
""" - source = safe_unicode(source) + source = safe_str(source) try: if flavored: source = cls._flavored_markdown(source) @@ -209,7 +209,7 @@ @classmethod def rst(cls, source, safe=True): - source = safe_unicode(source) + source = safe_str(source) try: from docutils.core import publish_parts from docutils.parsers.rst import directives @@ -219,7 +219,7 @@ docutils_settings.update({'input_encoding': 'unicode', 'report_level': 4}) - for k, v in docutils_settings.iteritems(): + for k, v in docutils_settings.items(): directives.register_directive(k, v) parts = publish_parts(source=source, diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/middleware/permanent_repo_url.py --- a/kallithea/lib/middleware/permanent_repo_url.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/middleware/permanent_repo_url.py Thu Feb 06 01:19:23 2020 +0100 @@ -20,7 +20,8 @@ """ -from kallithea.lib.utils import fix_repo_id_name, safe_str +from kallithea.lib.utils import fix_repo_id_name +from kallithea.lib.utils2 import safe_bytes, safe_str class PermanentRepoUrl(object): @@ -30,9 +31,11 @@ self.config = config def __call__(self, environ, start_response): - path_info = environ['PATH_INFO'] + # Extract path_info as get_path_info does, but do it explicitly because + # we also have to do the reverse operation when patching it back in + path_info = safe_str(environ['PATH_INFO'].encode('latin1')) if path_info.startswith('/'): # it must - path_info = '/' + safe_str(fix_repo_id_name(path_info[1:])) - environ['PATH_INFO'] = path_info + path_info = '/' + fix_repo_id_name(path_info[1:]) + environ['PATH_INFO'] = safe_bytes(path_info).decode('latin1') return self.application(environ, start_response) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/middleware/pygrack.py --- a/kallithea/lib/middleware/pygrack.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/middleware/pygrack.py Thu Feb 06 01:19:23 2020 +0100 @@ -33,7 +33,7 @@ from webob import Request, Response, exc import kallithea -from kallithea.lib.utils2 import safe_unicode +from kallithea.lib.utils2 import ascii_bytes from kallithea.lib.vcs import subprocessio @@ -87,7 +87,6 @@ :param path: """ - path = safe_unicode(path) assert path.startswith('/' + self.repo_name + '/') return path[len(self.repo_name) + 2:].strip('/') @@ -113,14 +112,14 @@ # ref_list # "0000" server_advert = '# service=%s\n' % git_command - packet_len = str(hex(len(server_advert) + 4)[2:].rjust(4, '0')).lower() + packet_len = hex(len(server_advert) + 4)[2:].rjust(4, '0').lower() _git_path = kallithea.CONFIG.get('git_path', 'git') cmd = [_git_path, git_command[4:], '--stateless-rpc', '--advertise-refs', self.content_path] log.debug('handling cmd %s', cmd) try: out = subprocessio.SubprocessIOChunker(cmd, - starting_values=[packet_len + server_advert + '0000'] + starting_values=[ascii_bytes(packet_len + server_advert + '0000')] ) except EnvironmentError as e: log.error(traceback.format_exc()) @@ -186,7 +185,7 @@ _path = self._get_fixedpath(req.path_info) if _path.startswith('info/refs'): app = self.inforefs - elif [a for a in self.valid_accepts if a in req.accept]: + elif req.accept.acceptable_offers(self.valid_accepts): app = self.backend try: resp = app(req, environ) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/middleware/simplegit.py --- a/kallithea/lib/middleware/simplegit.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/middleware/simplegit.py Thu Feb 06 01:19:23 2020 +0100 @@ -31,11 +31,10 @@ import logging import re -from kallithea.lib.base import BaseVCSController +from kallithea.lib.base import BaseVCSController, get_path_info from kallithea.lib.hooks import log_pull_action from kallithea.lib.middleware.pygrack import make_wsgi_app from kallithea.lib.utils import make_ui -from kallithea.lib.utils2 import safe_unicode from kallithea.model.db import Repository @@ -57,14 +56,14 @@ @classmethod def parse_request(cls, environ): - path_info = environ.get('PATH_INFO', '') + path_info = get_path_info(environ) m = GIT_PROTO_PAT.match(path_info) if m is None: return None class parsed_request(object): # See https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols#_the_smart_protocol - repo_name = safe_unicode(m.group(1).rstrip('/')) + repo_name = m.group(1).rstrip('/') cmd = m.group(2) query_string = environ['QUERY_STRING'] diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/middleware/simplehg.py --- a/kallithea/lib/middleware/simplehg.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/middleware/simplehg.py Thu Feb 06 01:19:23 2020 +0100 @@ -30,12 +30,13 @@ import logging import os -import urllib +import urllib.parse + +import mercurial.hgweb -from kallithea.lib.base import BaseVCSController +from kallithea.lib.base import BaseVCSController, get_path_info from kallithea.lib.utils import make_ui -from kallithea.lib.utils2 import safe_str, safe_unicode -from kallithea.lib.vcs.utils.hgcompat import hgweb_mod +from kallithea.lib.utils2 import safe_bytes log = logging.getLogger(__name__) @@ -99,12 +100,12 @@ http_accept = environ.get('HTTP_ACCEPT', '') if not http_accept.startswith('application/mercurial'): return None - path_info = environ.get('PATH_INFO', '') + path_info = get_path_info(environ) if not path_info.startswith('/'): # it must! return None class parsed_request(object): - repo_name = safe_unicode(path_info[1:].rstrip('/')) + repo_name = path_info[1:].rstrip('/') query_string = environ['QUERY_STRING'] @@ -120,7 +121,7 @@ break action = 'pull' for cmd_arg in hgarg[5:].split(';'): - cmd, _args = urllib.unquote_plus(cmd_arg).split(' ', 1) + cmd, _args = urllib.parse.unquote_plus(cmd_arg).split(' ', 1) op = cmd_mapping.get(cmd, 'push') if op != 'pull': assert op == 'push' @@ -136,13 +137,13 @@ """ Make an hgweb wsgi application. """ - str_repo_name = safe_str(parsed_request.repo_name) - repo_path = os.path.join(safe_str(self.basepath), str_repo_name) + repo_name = parsed_request.repo_name + repo_path = os.path.join(self.basepath, repo_name) baseui = make_ui(repo_path=repo_path) - hgweb_app = hgweb_mod.hgweb(repo_path, name=str_repo_name, baseui=baseui) + hgweb_app = mercurial.hgweb.hgweb(safe_bytes(repo_path), name=safe_bytes(repo_name), baseui=baseui) def wrapper_app(environ, start_response): - environ['REPO_NAME'] = str_repo_name # used by hgweb_mod.hgweb + environ['REPO_NAME'] = repo_name # used by mercurial.hgweb.hgweb return hgweb_app(environ, start_response) return wrapper_app diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/middleware/wrapper.py --- a/kallithea/lib/middleware/wrapper.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/middleware/wrapper.py Thu Feb 06 01:19:23 2020 +0100 @@ -29,8 +29,7 @@ import logging import time -from kallithea.lib.base import _get_access_path, _get_ip_addr -from kallithea.lib.utils2 import safe_unicode +from kallithea.lib.base import _get_ip_addr, get_path_info log = logging.getLogger(__name__) @@ -64,14 +63,14 @@ def __init__(self, result, meter, description): self._result_close = getattr(result, 'close', None) or (lambda: None) - self._next = iter(result).next + self._next = iter(result).__next__ self._meter = meter self._description = description def __iter__(self): return self - def next(self): + def __next__(self): chunk = self._next() self._meter.measure(chunk) return chunk @@ -91,7 +90,7 @@ meter = Meter(start_response) description = "Request from %s for %s" % ( _get_ip_addr(environ), - safe_unicode(_get_access_path(environ)), + get_path_info(environ), ) try: result = self.application(environ, meter.start_response) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/page.py --- a/kallithea/lib/page.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/page.py Thu Feb 06 01:19:23 2020 +0100 @@ -15,11 +15,11 @@ Custom paging classes """ import logging -import math -import re -from webhelpers2.html import HTML, literal -from webhelpers.paginate import Page as _Page +import paginate +import paginate_sqlalchemy +import sqlalchemy.orm +from webhelpers2.html import literal from kallithea.config.routing import url @@ -27,229 +27,36 @@ log = logging.getLogger(__name__) -class Page(_Page): - """ - Custom pager emitting Bootstrap paginators - """ - - def __init__(self, *args, **kwargs): - kwargs.setdefault('url', url.current) - _Page.__init__(self, *args, **kwargs) - - def _get_pos(self, cur_page, max_page, items): - edge = (items / 2) + 1 - if (cur_page <= edge): - radius = max(items / 2, items - cur_page) - elif (max_page - cur_page) < edge: - radius = (items - 1) - (max_page - cur_page) - else: - radius = items / 2 - - left = max(1, (cur_page - (radius))) - right = min(max_page, cur_page + (radius)) - return left, cur_page, right - - def _range(self, regexp_match): - """ - Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8'). - - Arguments: - - regexp_match - A "re" (regular expressions) match object containing the - radius of linked pages around the current page in - regexp_match.group(1) as a string - - This function is supposed to be called as a callable in - re.sub. - - """ - radius = int(regexp_match.group(1)) - - # Compute the first and last page number within the radius - # e.g. '1 .. 5 6 [7] 8 9 .. 12' - # -> leftmost_page = 5 - # -> rightmost_page = 9 - leftmost_page, _cur, rightmost_page = self._get_pos(self.page, - self.last_page, - (radius * 2) + 1) - nav_items = [] - - # Create a link to the first page (unless we are on the first page - # or there would be no need to insert '..' spacers) - if self.page != self.first_page and self.first_page < leftmost_page: - nav_items.append(HTML.li(self._pagerlink(self.first_page, self.first_page))) +class Page(paginate.Page): - # Insert dots if there are pages between the first page - # and the currently displayed page range - if leftmost_page - self.first_page > 1: - # Wrap in a SPAN tag if nolink_attr is set - text_ = '..' - if self.dotdot_attr: - text_ = HTML.span(c=text_, **self.dotdot_attr) - nav_items.append(HTML.li(text_)) - - for thispage in xrange(leftmost_page, rightmost_page + 1): - # Highlight the current page number and do not use a link - text_ = str(thispage) - if thispage == self.page: - # Wrap in a SPAN tag if nolink_attr is set - if self.curpage_attr: - text_ = HTML.li(HTML.span(c=text_), **self.curpage_attr) - nav_items.append(text_) - # Otherwise create just a link to that page - else: - nav_items.append(HTML.li(self._pagerlink(thispage, text_))) - - # Insert dots if there are pages between the displayed - # page numbers and the end of the page range - if self.last_page - rightmost_page > 1: - text_ = '..' - # Wrap in a SPAN tag if nolink_attr is set - if self.dotdot_attr: - text_ = HTML.span(c=text_, **self.dotdot_attr) - nav_items.append(HTML.li(text_)) - - # Create a link to the very last page (unless we are on the last - # page or there would be no need to insert '..' spacers) - if self.page != self.last_page and rightmost_page < self.last_page: - nav_items.append(HTML.li(self._pagerlink(self.last_page, self.last_page))) - - #_page_link = url.current() - #nav_items.append(literal('' % (_page_link, str(int(self.page)+1)))) - #nav_items.append(literal('' % (_page_link, str(int(self.page)+1)))) - return self.separator.join(nav_items) - - def pager(self, format='
    $link_previous ~2~ $link_next
', page_param='page', partial_param='partial', - show_if_single_page=False, separator=' ', onclick=None, - symbol_first='<<', symbol_last='>>', - symbol_previous='<', symbol_next='>', - link_attr=None, - curpage_attr=None, - dotdot_attr=None, **kwargs - ): - self.curpage_attr = curpage_attr or {'class': 'active'} - self.separator = separator - self.pager_kwargs = kwargs - self.page_param = page_param - self.partial_param = partial_param - self.onclick = onclick - self.link_attr = link_attr or {'class': 'pager_link', 'rel': 'prerender'} - self.dotdot_attr = dotdot_attr or {'class': 'pager_dotdot'} + def __init__(self, collection, + page=1, items_per_page=20, item_count=None, + **kwargs): + if isinstance(collection, sqlalchemy.orm.query.Query): + collection = paginate_sqlalchemy.SqlalchemyOrmWrapper(collection) + paginate.Page.__init__(self, collection, page=page, items_per_page=items_per_page, item_count=item_count, + url_maker=lambda page: url.current(page=page, **kwargs)) - # Don't show navigator if there is no more than one page - if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page): - return '' - - from string import Template - # Replace ~...~ in token format by range of pages - result = re.sub(r'~(\d+)~', self._range, format) - - # Interpolate '%' variables - result = Template(result).safe_substitute({ - 'first_page': self.first_page, - 'last_page': self.last_page, - 'page': self.page, - 'page_count': self.page_count, - 'items_per_page': self.items_per_page, - 'first_item': self.first_item, - 'last_item': self.last_item, - 'item_count': self.item_count, - 'link_first': self.page > self.first_page and - self._pagerlink(self.first_page, symbol_first) or '', - 'link_last': self.page < self.last_page and - self._pagerlink(self.last_page, symbol_last) or '', - 'link_previous': HTML.li(self.previous_page and - self._pagerlink(self.previous_page, symbol_previous) - or HTML.a(symbol_previous)), - 'link_next': HTML.li(self.next_page and - self._pagerlink(self.next_page, symbol_next) - or HTML.a(symbol_next)), - }) - - return literal(result) - - -class RepoPage(Page): - - def __init__(self, collection, page=1, items_per_page=20, - item_count=None, **kwargs): - - """Create a "RepoPage" instance. special pager for paging - repository - """ - # TODO: call baseclass __init__ - self._url_generator = kwargs.pop('url', url.current) - - # Safe the kwargs class-wide so they can be used in the pager() method - self.kwargs = kwargs - - # Save a reference to the collection - self.original_collection = collection - - self.collection = collection + def pager(self): + return literal( + paginate.Page.pager(self, + format='
    $link_previous\n~4~$link_next
', + link_attr={'class': 'pager_link'}, + dotdot_attr={'class': 'pager_dotdot'}, + separator='\n', + )) - # The self.page is the number of the current page. - # The first page has the number 1! - try: - self.page = int(page) # make it int() if we get it as a string - except (ValueError, TypeError): - log.error("Invalid page value: %r", page) - self.page = 1 - - self.items_per_page = items_per_page - - # Unless the user tells us how many items the collections has - # we calculate that ourselves. - if item_count is not None: - self.item_count = item_count - else: - self.item_count = len(self.collection) - - # Compute the number of the first and last available page - if self.item_count > 0: - self.first_page = 1 - self.page_count = int(math.ceil(float(self.item_count) / - self.items_per_page)) - self.last_page = self.first_page + self.page_count - 1 - - # Make sure that the requested page number is the range of - # valid pages - if self.page > self.last_page: - self.page = self.last_page - elif self.page < self.first_page: - self.page = self.first_page + @staticmethod + def default_link_tag(item): + # based on the base class implementation, but wrapping results in
  • , and with different handling of current_page + text = item['value'] + if item['type'] == 'current_page': # we need active on the li and can thus not use curpage_attr + return '''
  • %s
  • ''' % text - # Note: the number of items on this page can be less than - # items_per_page if the last page is not full - self.first_item = max(0, (self.item_count) - (self.page * - items_per_page)) - self.last_item = ((self.item_count - 1) - items_per_page * - (self.page - 1)) - - self.items = list(self.collection[self.first_item:self.last_item + 1]) - - # Links to previous and next page - if self.page > self.first_page: - self.previous_page = self.page - 1 - else: - self.previous_page = None - - if self.page < self.last_page: - self.next_page = self.page + 1 - else: - self.next_page = None - - # No items available + if not item['href'] or item['type'] == 'span': + if item['attrs']: + text = paginate.make_html_tag('span', **item['attrs']) + text + '' else: - self.first_page = None - self.page_count = 0 - self.last_page = None - self.first_item = None - self.last_item = None - self.previous_page = None - self.next_page = None - self.items = [] - - # This is a subclass of the 'list' type. Initialise the list now. - list.__init__(self, reversed(self.items)) + target_url = item['href'] + text = paginate.make_html_tag('a', text=text, href=target_url, **item['attrs']) + return '''
  • %s
  • ''' % text diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/paster_commands/template.ini.mako --- a/kallithea/lib/paster_commands/template.ini.mako Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/paster_commands/template.ini.mako Thu Feb 06 01:19:23 2020 +0100 @@ -220,7 +220,7 @@ <%text>## used, which is correct in many cases but for example not when using uwsgi. <%text>## If you change this setting, you should reinstall the Git hooks via <%text>## Admin > Settings > Remap and Rescan. -# git_hook_interpreter = /srv/kallithea/venv/bin/python2 +# git_hook_interpreter = /srv/kallithea/venv/bin/python3 %if git_hook_interpreter: git_hook_interpreter = ${git_hook_interpreter} %endif diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/pidlock.py --- a/kallithea/lib/pidlock.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/pidlock.py Thu Feb 06 01:19:23 2020 +0100 @@ -137,6 +137,6 @@ dir_, file_ = os.path.split(pidfile) if not os.path.isdir(dir_): os.makedirs(dir_) - with open(self.pidfile, 'wb') as f: + with open(self.pidfile, 'w') as f: f.write(lockname) self.held = True diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/pygmentsutils.py --- a/kallithea/lib/pygmentsutils.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/pygmentsutils.py Thu Feb 06 01:19:23 2020 +0100 @@ -26,7 +26,6 @@ """ from collections import defaultdict -from itertools import ifilter from pygments import lexers @@ -59,15 +58,11 @@ """ Get list of known indexable filenames from pygment lexer internals """ - filenames = [] - - def likely_filename(s): - return s.find('*') == -1 and s.find('[') == -1 - for lx, t in sorted(lexers.LEXERS.items()): - for f in ifilter(likely_filename, t[-2]): - filenames.append(f) + for f in t[-2]: + if '*' not in f and '[' not in f: + filenames.append(f) return filenames diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/rcmail/message.py --- a/kallithea/lib/rcmail/message.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/rcmail/message.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,7 +25,7 @@ @property def data(self): - if isinstance(self._data, basestring): + if isinstance(self._data, str): return self._data self._data = self._data.read() return self._data diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/rcmail/response.py --- a/kallithea/lib/rcmail/response.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/rcmail/response.py Thu Feb 06 01:19:23 2020 +0100 @@ -87,7 +87,7 @@ def __delitem__(self, key): del self.headers[normalize_header(key)] - def __nonzero__(self): + def __bool__(self): return self.body is not None or len(self.headers) > 0 or len(self.parts) > 0 def keys(self): @@ -339,20 +339,20 @@ try: out = MIMEPart(ctype, **params) - except TypeError as exc: # pragma: no cover + except TypeError as e: # pragma: no cover raise EncodingError("Content-Type malformed, not allowed: %r; " - "%r (Python ERROR: %s" % - (ctype, params, exc.message)) + "%r (Python ERROR: %s)" % + (ctype, params, e.args[0])) for k in mail.keys(): if k in ADDRESS_HEADERS_WHITELIST: - out[k.encode('ascii')] = header_to_mime_encoding( + out[k] = header_to_mime_encoding( mail[k], not_email=False, separator=separator ) else: - out[k.encode('ascii')] = header_to_mime_encoding( + out[k] = header_to_mime_encoding( mail[k], not_email=True ) @@ -422,7 +422,7 @@ return "" encoder = Charset(DEFAULT_ENCODING) - if type(value) == list: + if isinstance(value, list): return separator.join(properly_encode_header( v, encoder, not_email) for v in value) else: @@ -443,12 +443,12 @@ check different, then change this. """ try: - return value.encode("ascii") - except UnicodeEncodeError: + value.encode("ascii") + return value + except UnicodeError: if not not_email and VALUE_IS_EMAIL_ADDRESS(value): # this could have an email address, make sure we don't screw it up name, address = parseaddr(value) - return '"%s" <%s>' % ( - encoder.header_encode(name.encode("utf-8")), address) + return '"%s" <%s>' % (encoder.header_encode(name), address) - return encoder.header_encode(value.encode("utf-8")) + return encoder.header_encode(value) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/rcmail/smtp_mailer.py --- a/kallithea/lib/rcmail/smtp_mailer.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/rcmail/smtp_mailer.py Thu Feb 06 01:19:23 2020 +0100 @@ -64,7 +64,7 @@ def send(self, recipients=None, subject='', body='', html='', attachment_files=None, headers=None): recipients = recipients or [] - if isinstance(recipients, basestring): + if isinstance(recipients, str): recipients = [recipients] if headers is None: headers = {} diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/recaptcha.py --- a/kallithea/lib/recaptcha.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/recaptcha.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import json -import urllib -import urllib2 +import urllib.parse +import urllib.request class RecaptchaResponse(object): @@ -26,17 +26,17 @@ return RecaptchaResponse(is_valid=False, error_code='incorrect-captcha-sol') def encode_if_necessary(s): - if isinstance(s, unicode): + if isinstance(s, str): return s.encode('utf-8') return s - params = urllib.urlencode({ + params = urllib.parse.urlencode({ 'secret': encode_if_necessary(private_key), 'remoteip': encode_if_necessary(remoteip), 'response': encode_if_necessary(g_recaptcha_response), - }) + }).encode('ascii') - req = urllib2.Request( + req = urllib.request.Request( url="https://www.google.com/recaptcha/api/siteverify", data=params, headers={ @@ -45,7 +45,7 @@ } ) - httpresp = urllib2.urlopen(req) + httpresp = urllib.request.urlopen(req) return_values = json.loads(httpresp.read()) httpresp.close() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/ssh.py --- a/kallithea/lib/ssh.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/ssh.py Thu Feb 06 01:19:23 2020 +0100 @@ -21,12 +21,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import binascii +import base64 import logging import re from tg.i18n import ugettext as _ +from kallithea.lib.utils2 import ascii_bytes, ascii_str + log = logging.getLogger(__name__) @@ -42,37 +44,39 @@ >>> parse_pub_key('') Traceback (most recent call last): ... - SshKeyParseError: SSH key is missing + kallithea.lib.ssh.SshKeyParseError: SSH key is missing >>> parse_pub_key('''AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''') Traceback (most recent call last): ... - SshKeyParseError: Incorrect SSH key - it must have both a key type and a base64 part + kallithea.lib.ssh.SshKeyParseError: Incorrect SSH key - it must have both a key type and a base64 part, like 'ssh-rsa ASRNeaZu4FA...xlJp=' >>> parse_pub_key('''abc AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''') Traceback (most recent call last): ... - SshKeyParseError: Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)' + kallithea.lib.ssh.SshKeyParseError: Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)' >>> parse_pub_key('''ssh-rsa AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''') Traceback (most recent call last): ... - SshKeyParseError: Incorrect SSH key - failed to decode base64 part 'AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ' + kallithea.lib.ssh.SshKeyParseError: Incorrect SSH key - failed to decode base64 part 'AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ' >>> parse_pub_key('''ssh-rsa AAAAB2NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ==''') Traceback (most recent call last): ... - SshKeyParseError: Incorrect SSH key - base64 part is not 'ssh-rsa' as claimed but 'csh-rsa' + kallithea.lib.ssh.SshKeyParseError: Incorrect SSH key - base64 part is not 'ssh-rsa' as claimed but 'csh-rsa' >>> parse_pub_key('''ssh-rsa AAAAB3NzaC1yc2EAAAA'LVGhpcyBpcyBmYWtlIQ''') Traceback (most recent call last): ... - SshKeyParseError: Incorrect SSH key - unexpected characters in base64 part "AAAAB3NzaC1yc2EAAAA'LVGhpcyBpcyBmYWtlIQ" + kallithea.lib.ssh.SshKeyParseError: Incorrect SSH key - unexpected characters in base64 part "AAAAB3NzaC1yc2EAAAA'LVGhpcyBpcyBmYWtlIQ" >>> parse_pub_key(''' ssh-rsa AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ== and a comment ... ''') - ('ssh-rsa', '\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x0bThis is fake!', 'and a comment\n') + ('ssh-rsa', b'\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x0bThis is fake!', 'and a comment\n') + >>> parse_pub_key('''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP1NA2kBQIKe74afUXmIWD9ByDYQJqUwW44Y4gJOBRuo''') + ('ssh-ed25519', b'\x00\x00\x00\x0bssh-ed25519\x00\x00\x00 \xfdM\x03i\x01@\x82\x9e\xef\x86\x9fQy\x88X?A\xc86\x10&\xa50[\x8e\x18\xe2\x02N\x05\x1b\xa8', '') """ if not ssh_key: raise SshKeyParseError(_("SSH key is missing")) parts = ssh_key.split(None, 2) if len(parts) < 2: - raise SshKeyParseError(_("Incorrect SSH key - it must have both a key type and a base64 part")) + raise SshKeyParseError(_("Incorrect SSH key - it must have both a key type and a base64 part, like 'ssh-rsa ASRNeaZu4FA...xlJp='")) keytype, keyvalue, comment = (parts + [''])[:3] if keytype not in ('ssh-rsa', 'ssh-dss', 'ssh-ed25519'): @@ -82,19 +86,31 @@ raise SshKeyParseError(_("Incorrect SSH key - unexpected characters in base64 part %r") % keyvalue) try: - decoded = keyvalue.decode('base64') - except binascii.Error: + key_bytes = base64.b64decode(keyvalue) + except base64.binascii.Error: raise SshKeyParseError(_("Incorrect SSH key - failed to decode base64 part %r") % keyvalue) - if not decoded.startswith('\x00\x00\x00\x07' + str(keytype) + '\x00'): - raise SshKeyParseError(_("Incorrect SSH key - base64 part is not %r as claimed but %r") % (str(keytype), str(decoded[4:].split('\0', 1)[0]))) + if not key_bytes.startswith(b'\x00\x00\x00%c%s\x00' % (len(keytype), ascii_bytes(keytype))): + raise SshKeyParseError(_("Incorrect SSH key - base64 part is not %r as claimed but %r") % (keytype, ascii_str(key_bytes[4:].split(b'\0', 1)[0]))) - return keytype, decoded, comment + return keytype, key_bytes, comment SSH_OPTIONS = 'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding' +def _safe_check(s, rec = re.compile('^[a-zA-Z0-9+/]+={0,2}$')): + """Return true if s really has the right content for base64 encoding and only contains safe characters + >>> _safe_check('asdf') + True + >>> _safe_check('as df') + False + >>> _safe_check('AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ==') + True + """ + return rec.match(s) is not None + + def authorized_keys_line(kallithea_cli_path, config_file, key): """ Return a line as it would appear in .authorized_keys @@ -107,11 +123,14 @@ 'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="/srv/kallithea/venv/bin/kallithea-cli ssh-serve -c /srv/kallithea/my.ini 7 17" ssh-rsa AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ==\\n' """ try: - keytype, decoded, comment = parse_pub_key(key.public_key) + keytype, key_bytes, comment = parse_pub_key(key.public_key) except SshKeyParseError: return '# Invalid Kallithea SSH key: %s %s\n' % (key.user.user_id, key.user_ssh_key_id) - mimekey = decoded.encode('base64').replace('\n', '') + base64_key = ascii_str(base64.b64encode(key_bytes)) + assert '\n' not in base64_key + if not _safe_check(base64_key): + return '# Invalid Kallithea SSH key - bad base64 encoding: %s %s\n' % (key.user.user_id, key.user_ssh_key_id) return '%s,command="%s ssh-serve -c %s %s %s" %s %s\n' % ( SSH_OPTIONS, kallithea_cli_path, config_file, key.user.user_id, key.user_ssh_key_id, - keytype, mimekey) + keytype, base64_key) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/timerproxy.py --- a/kallithea/lib/timerproxy.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/timerproxy.py Thu Feb 06 01:19:23 2020 +0100 @@ -20,7 +20,7 @@ log = logging.getLogger('timerproxy') -BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38) +BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30, 38) def color_sql(sql): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/utils.py --- a/kallithea/lib/utils.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/utils.py Thu Feb 06 01:19:23 2020 +0100 @@ -33,19 +33,22 @@ import traceback from distutils.version import StrictVersion -import beaker -from beaker.cache import _cache_decorate +import beaker.cache +import mercurial.config +import mercurial.ui from tg.i18n import ugettext as _ +import kallithea.config.conf from kallithea.lib.exceptions import HgsubversionImportError -from kallithea.lib.utils2 import get_current_authuser, safe_str, safe_unicode -from kallithea.lib.vcs.exceptions import VCSError +from kallithea.lib.utils2 import ascii_bytes, aslist, get_current_authuser, safe_bytes, safe_str +from kallithea.lib.vcs.backends.git.repository import GitRepository +from kallithea.lib.vcs.backends.hg.repository import MercurialRepository +from kallithea.lib.vcs.conf import settings +from kallithea.lib.vcs.exceptions import RepositoryError, VCSError from kallithea.lib.vcs.utils.fakemod import create_module from kallithea.lib.vcs.utils.helpers import get_scm -from kallithea.lib.vcs.utils.hgcompat import config, ui from kallithea.model import meta from kallithea.model.db import RepoGroup, Repository, Setting, Ui, User, UserGroup, UserLog -from kallithea.model.repo_group import RepoGroupModel log = logging.getLogger(__name__) @@ -102,7 +105,6 @@ rest = '/' + rest_ repo_id = _get_permanent_id(first) if repo_id is not None: - from kallithea.model.db import Repository repo = Repository.get(repo_id) if repo is not None: return repo.repo_name + rest @@ -130,7 +132,7 @@ if getattr(user, 'user_id', None): user_obj = User.get(user.user_id) - elif isinstance(user, basestring): + elif isinstance(user, str): user_obj = User.get_by_username(user) else: raise Exception('You have to provide a user object or a username') @@ -138,7 +140,7 @@ if getattr(repo, 'repo_id', None): repo_obj = Repository.get(repo.repo_id) repo_name = repo_obj.repo_name - elif isinstance(repo, basestring): + elif isinstance(repo, str): repo_name = repo.lstrip('/') repo_obj = Repository.get_by_repo_name(repo_name) else: @@ -148,7 +150,7 @@ user_log = UserLog() user_log.user_id = user_obj.user_id user_log.username = user_obj.username - user_log.action = safe_unicode(action) + user_log.action = action user_log.repository = repo_obj user_log.repository_name = repo_name @@ -158,7 +160,7 @@ meta.Session().add(user_log) log.info('Logging action:%s on %s by user:%s ip:%s', - action, safe_unicode(repo), user_obj, ipaddr) + action, repo, user_obj, ipaddr) if commit: meta.Session().commit() @@ -172,7 +174,7 @@ """ # remove ending slash for better results - path = safe_str(path.rstrip(os.sep)) + path = path.rstrip(os.sep) log.debug('now scanning in %s', path) def isdir(*n): @@ -225,7 +227,6 @@ def is_valid_repo_uri(repo_type, url, ui): """Check if the url seems like a valid remote repo location - raise an Exception if any problems""" if repo_type == 'hg': - from kallithea.lib.vcs.backends.hg.repository import MercurialRepository if url.startswith('http') or url.startswith('ssh'): # initially check if it's at least the proper URL # or does it pass basic auth @@ -243,7 +244,6 @@ raise Exception('URI %s not allowed' % (url,)) elif repo_type == 'git': - from kallithea.lib.vcs.backends.git.repository import GitRepository if url.startswith('http') or url.startswith('git'): # initially check if it's at least the proper URL # or does it pass basic auth @@ -269,7 +269,7 @@ :return True: if given path is a valid repository """ # TODO: paranoid security checks? - full_path = os.path.join(safe_str(base_path), safe_str(repo_name)) + full_path = os.path.join(base_path, repo_name) try: scm_ = get_scm(full_path) @@ -287,7 +287,7 @@ :param repo_name: :param base_path: """ - full_path = os.path.join(safe_str(base_path), safe_str(repo_group_name)) + full_path = os.path.join(base_path, repo_group_name) # check if it's not a repo if is_valid_repo(repo_group_name, base_path): @@ -322,49 +322,46 @@ 'ui', 'web', ] -def make_ui(repo_path=None, clear_session=True): +def make_ui(repo_path=None): """ Create an Mercurial 'ui' object based on database Ui settings, possibly augmenting with content from a hgrc file. """ - baseui = ui.ui() + baseui = mercurial.ui.ui() # clean the baseui object - baseui._ocfg = config.config() - baseui._ucfg = config.config() - baseui._tcfg = config.config() + baseui._ocfg = mercurial.config.config() + baseui._ucfg = mercurial.config.config() + baseui._tcfg = mercurial.config.config() sa = meta.Session() for ui_ in sa.query(Ui).all(): if ui_.ui_active: - ui_val = '' if ui_.ui_value is None else safe_str(ui_.ui_value) log.debug('config from db: [%s] %s=%r', ui_.ui_section, - ui_.ui_key, ui_val) - baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key), - ui_val) - if clear_session: - meta.Session.remove() + ui_.ui_key, ui_.ui_value) + baseui.setconfig(ascii_bytes(ui_.ui_section), ascii_bytes(ui_.ui_key), + b'' if ui_.ui_value is None else safe_bytes(ui_.ui_value)) # force set push_ssl requirement to False, Kallithea handles that - baseui.setconfig('web', 'push_ssl', False) - baseui.setconfig('web', 'allow_push', '*') + baseui.setconfig(b'web', b'push_ssl', False) + baseui.setconfig(b'web', b'allow_push', b'*') # prevent interactive questions for ssh password / passphrase - ssh = baseui.config('ui', 'ssh', default='ssh') - baseui.setconfig('ui', 'ssh', '%s -oBatchMode=yes -oIdentitiesOnly=yes' % ssh) + ssh = baseui.config(b'ui', b'ssh', default=b'ssh') + baseui.setconfig(b'ui', b'ssh', b'%s -oBatchMode=yes -oIdentitiesOnly=yes' % ssh) # push / pull hooks - baseui.setconfig('hooks', 'changegroup.kallithea_log_push_action', 'python:kallithea.lib.hooks.log_push_action') - baseui.setconfig('hooks', 'outgoing.kallithea_log_pull_action', 'python:kallithea.lib.hooks.log_pull_action') + baseui.setconfig(b'hooks', b'changegroup.kallithea_log_push_action', b'python:kallithea.lib.hooks.log_push_action') + baseui.setconfig(b'hooks', b'outgoing.kallithea_log_pull_action', b'python:kallithea.lib.hooks.log_pull_action') if repo_path is not None: hgrc_path = os.path.join(repo_path, '.hg', 'hgrc') if os.path.isfile(hgrc_path): log.debug('reading hgrc from %s', hgrc_path) - cfg = config.config() - cfg.read(hgrc_path) + cfg = mercurial.config.config() + cfg.read(safe_bytes(hgrc_path)) for section in ui_sections: for k, v in cfg.items(section): log.debug('config from file: [%s] %s=%s', section, k, v) - baseui.setconfig(safe_str(section), safe_str(k), safe_str(v)) + baseui.setconfig(ascii_bytes(section), ascii_bytes(k), safe_bytes(v)) else: log.debug('hgrc file is not present at %s, skipping...', hgrc_path) @@ -377,12 +374,9 @@ :param config: """ - try: - hgsettings = Setting.get_app_settings() - for k, v in hgsettings.items(): - config[k] = v - finally: - meta.Session.remove() + hgsettings = Setting.get_app_settings() + for k, v in hgsettings.items(): + config[k] = v def set_vcs_config(config): @@ -391,16 +385,14 @@ :param config: kallithea.CONFIG """ - from kallithea.lib.vcs import conf - from kallithea.lib.utils2 import aslist - conf.settings.BACKENDS = { + settings.BACKENDS = { 'hg': 'kallithea.lib.vcs.backends.hg.MercurialRepository', 'git': 'kallithea.lib.vcs.backends.git.GitRepository', } - conf.settings.GIT_EXECUTABLE_PATH = config.get('git_path', 'git') - conf.settings.GIT_REV_FILTER = config.get('git_rev_filter', '--all').strip() - conf.settings.DEFAULT_ENCODINGS = aslist(config.get('default_encoding', + settings.GIT_EXECUTABLE_PATH = config.get('git_path', 'git') + settings.GIT_REV_FILTER = config.get('git_rev_filter', '--all').strip() + settings.DEFAULT_ENCODINGS = aslist(config.get('default_encoding', 'utf-8'), sep=',') @@ -410,13 +402,11 @@ :param config: kallithea.CONFIG """ - from kallithea.config import conf - log.debug('adding extra into INDEX_EXTENSIONS') - conf.INDEX_EXTENSIONS.extend(re.split(r'\s+', config.get('index.extensions', ''))) + kallithea.config.conf.INDEX_EXTENSIONS.extend(re.split(r'\s+', config.get('index.extensions', ''))) log.debug('adding extra into INDEX_FILENAMES') - conf.INDEX_FILENAMES.extend(re.split(r'\s+', config.get('index.filenames', ''))) + kallithea.config.conf.INDEX_FILENAMES.extend(re.split(r'\s+', config.get('index.filenames', ''))) def map_groups(path): @@ -427,6 +417,7 @@ :param paths: full path to repository """ + from kallithea.model.repo_group import RepoGroupModel sa = meta.Session() groups = path.split(Repository.url_sep()) parent = None @@ -459,14 +450,14 @@ return group -def repo2db_mapper(initial_repo_list, remove_obsolete=False, +def repo2db_mapper(initial_repo_dict, remove_obsolete=False, install_git_hooks=False, user=None, overwrite_git_hooks=False): """ - maps all repos given in initial_repo_list, non existing repositories + maps all repos given in initial_repo_dict, non existing repositories are created, if remove_obsolete is True it also check for db entries - that are not in initial_repo_list and removes them. + that are not in initial_repo_dict and removes them. - :param initial_repo_list: list of repositories found by scanning methods + :param initial_repo_dict: mapping with repositories found by scanning methods :param remove_obsolete: check for obsolete entries in database :param install_git_hooks: if this is True, also check and install git hook for a repo if missing @@ -487,10 +478,9 @@ enable_downloads = defs.get('repo_enable_downloads') private = defs.get('repo_private') - for name, repo in initial_repo_list.items(): + for name, repo in initial_repo_dict.items(): group = map_groups(name) - unicode_name = safe_unicode(name) - db_repo = repo_model.get_by_repo_name(unicode_name) + db_repo = repo_model.get_by_repo_name(name) # found repo that is on filesystem not in Kallithea database if not db_repo: log.info('repository %s not found, creating now', name) @@ -526,9 +516,8 @@ removed = [] # remove from database those repositories that are not in the filesystem - unicode_initial_repo_list = set(safe_unicode(name) for name in initial_repo_list) for repo in sa.query(Repository).all(): - if repo.repo_name not in unicode_initial_repo_list: + if repo.repo_name not in initial_repo_dict: if remove_obsolete: log.debug("Removing non-existing repository found in db `%s`", repo.repo_name) @@ -544,9 +533,6 @@ def load_rcextensions(root_path): - import kallithea - from kallithea.config import conf - path = os.path.join(root_path, 'rcextensions', '__init__.py') if os.path.isfile(path): rcext = create_module('rc', path) @@ -554,17 +540,17 @@ log.debug('Found rcextensions now loading %s...', rcext) # Additional mappings that are not present in the pygments lexers - conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {})) + kallithea.config.conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {})) # OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present) if getattr(EXT, 'INDEX_EXTENSIONS', []): log.debug('settings custom INDEX_EXTENSIONS') - conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', []) + kallithea.config.conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', []) # ADDITIONAL MAPPINGS log.debug('adding extra into INDEX_EXTENSIONS') - conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', [])) + kallithea.config.conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', [])) # auto check if the module is not missing any data, set to default if is # this will help autoupdate new feature of rcext module @@ -585,28 +571,33 @@ Checks what version of git is installed on the system, and raise a system exit if it's too old for Kallithea to work properly. """ - from kallithea import BACKENDS - from kallithea.lib.vcs.backends.git.repository import GitRepository - from kallithea.lib.vcs.conf import settings - - if 'git' not in BACKENDS: + if 'git' not in kallithea.BACKENDS: return None if not settings.GIT_EXECUTABLE_PATH: log.warning('No git executable configured - check "git_path" in the ini file.') return None - stdout, stderr = GitRepository._run_git_command(['--version'], _bare=True, - _safe=True) + try: + stdout, stderr = GitRepository._run_git_command(['--version']) + except RepositoryError as e: + # message will already have been logged as error + log.warning('No working git executable found - check "git_path" in the ini file.') + return None if stderr: - log.warning('Error/stderr from "%s --version": %r', settings.GIT_EXECUTABLE_PATH, stderr) + log.warning('Error/stderr from "%s --version":\n%s', settings.GIT_EXECUTABLE_PATH, safe_str(stderr)) - m = re.search(r"\d+.\d+.\d+", stdout) + if not stdout: + log.warning('No working git executable found - check "git_path" in the ini file.') + return None + + output = safe_str(stdout).strip() + m = re.search(r"\d+.\d+.\d+", output) if m: ver = StrictVersion(m.group(0)) log.debug('Git executable: "%s", version %s (parsed from: "%s")', - settings.GIT_EXECUTABLE_PATH, ver, stdout.strip()) + settings.GIT_EXECUTABLE_PATH, ver, output) if ver < git_req_ver: log.error('Kallithea detected %s version %s, which is too old ' 'for the system to function properly. ' @@ -618,8 +609,8 @@ sys.exit(1) else: ver = StrictVersion('0.0.0') - log.warning('Error finding version number in "%s --version" stdout: %r', - settings.GIT_EXECUTABLE_PATH, stdout.strip()) + log.warning('Error finding version number in "%s --version" stdout:\n%s', + settings.GIT_EXECUTABLE_PATH, output) return ver @@ -628,36 +619,6 @@ # CACHE RELATED METHODS #=============================================================================== -# set cache regions for beaker so celery can utilise it -def setup_cache_regions(settings): - # Create dict with just beaker cache configs with prefix stripped - cache_settings = {'regions': None} - prefix = 'beaker.cache.' - for key in settings: - if key.startswith(prefix): - name = key[len(prefix):] - cache_settings[name] = settings[key] - # Find all regions, apply defaults, and apply to beaker - if cache_settings['regions']: - for region in cache_settings['regions'].split(','): - region = region.strip() - prefix = region + '.' - region_settings = {} - for key in cache_settings: - if key.startswith(prefix): - name = key[len(prefix):] - region_settings[name] = cache_settings[key] - region_settings.setdefault('expire', - cache_settings.get('expire', '60')) - region_settings.setdefault('lock_dir', - cache_settings.get('lock_dir')) - region_settings.setdefault('data_dir', - cache_settings.get('data_dir')) - region_settings.setdefault('type', - cache_settings.get('type', 'memory')) - beaker.cache.cache_regions[region] = region_settings - - def conditional_cache(region, prefix, condition, func): """ @@ -680,6 +641,6 @@ if condition: log.debug('conditional_cache: True, wrapping call of ' 'func: %s into %s region cache' % (region, func)) - wrapped = _cache_decorate((prefix,), None, None, region)(func) + wrapped = beaker.cache._cache_decorate((prefix,), None, None, region)(func) return wrapped diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/utils2.py --- a/kallithea/lib/utils2.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/utils2.py Thu Feb 06 01:19:23 2020 +0100 @@ -31,18 +31,19 @@ import binascii import datetime +import json import os import pwd import re import time -import urllib +import urllib.parse import urlobject from tg.i18n import ugettext as _ from tg.i18n import ungettext from webhelpers2.text import collapse, remove_formatting, strip_tags -from kallithea.lib.compat import json +from kallithea.lib.vcs.utils import ascii_bytes, ascii_str, safe_bytes, safe_str # re-export from kallithea.lib.vcs.utils.lazy import LazyProperty @@ -71,7 +72,7 @@ :param sep: :param strip: """ - if isinstance(obj, (basestring)): + if isinstance(obj, (str)): lst = obj.split(sep) if strip: lst = [v.strip() for v in lst] @@ -98,14 +99,12 @@ :rtype: str :return: converted line according to mode """ - from string import replace - if mode == 0: - line = replace(line, '\r\n', '\n') - line = replace(line, '\r', '\n') + line = line.replace('\r\n', '\n') + line = line.replace('\r', '\n') elif mode == 1: - line = replace(line, '\r\n', '\r') - line = replace(line, '\n', '\r') + line = line.replace('\r\n', '\r') + line = line.replace('\n', '\r') elif mode == 2: line = re.sub("\r(?!\n)|(? outputs long shas (and we need all 40 characters) # --root ==> doesn't put '^' character for boundaries # -r sha ==> blames for the given revision - so, se = self.repository.run_git_command(cmd) + so = self.repository.run_git_command(cmd) for i, blame_line in enumerate(so.split('\n')[:-1]): - ln_no = i + 1 sha, line = re.split(r' ', blame_line, 1) - yield (ln_no, sha, lambda: self.repository.get_changeset(sha), line) + yield (i + 1, sha, lambda sha=sha: self.repository.get_changeset(sha), line) def fill_archive(self, stream=None, kind='tgz', prefix=None, subrepos=False): @@ -353,12 +343,15 @@ :raise ImproperArchiveTypeError: If given kind is wrong. :raise VcsError: If given stream is None - """ - allowed_kinds = settings.ARCHIVE_SPECS.keys() + allowed_kinds = settings.ARCHIVE_SPECS if kind not in allowed_kinds: raise ImproperArchiveTypeError('Archive kind not supported use one' - 'of %s' % allowed_kinds) + 'of %s' % ' '.join(allowed_kinds)) + + if stream is None: + raise VCSError('You need to pass in a valid stream for filling' + ' with archival data') if prefix is None: prefix = '%s-%s' % (self.repository.name, self.short_id) @@ -394,6 +387,12 @@ popen.communicate() def get_nodes(self, path): + """ + Returns combined ``DirNode`` and ``FileNode`` objects list representing + state of changeset at the given ``path``. If node at the given ``path`` + is not instance of ``DirNode``, ChangesetError would be raised. + """ + if self._get_kind(path) != NodeKind.DIR: raise ChangesetError("Directory does not exist for revision %s at " " '%s'" % (self.revision, path)) @@ -403,16 +402,15 @@ dirnodes = [] filenodes = [] als = self.repository.alias - for name, stat, id in tree.iteritems(): + for name, stat, id in tree.items(): + obj_path = safe_str(name) if path != '': - obj_path = '/'.join((path, name)) - else: - obj_path = name + obj_path = '/'.join((path, obj_path)) if objects.S_ISGITLINK(stat): root_tree = self.repository._repo[self._tree_id] - cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(root_tree['.gitmodules'][1]).data)) - url = cf.get(('submodule', obj_path), 'url') - dirnodes.append(SubModuleNode(obj_path, url=url, changeset=id, + cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(root_tree[b'.gitmodules'][1]).data)) + url = ascii_str(cf.get(('submodule', obj_path), 'url')) + dirnodes.append(SubModuleNode(obj_path, url=url, changeset=ascii_str(id), alias=als)) continue @@ -434,8 +432,10 @@ return nodes def get_node(self, path): - if isinstance(path, unicode): - path = path.encode('utf-8') + """ + Returns ``Node`` object from the given ``path``. If there is no node at + the given ``path``, ``ChangesetError`` would be raised. + """ path = self._fix_path(path) if path not in self.nodes: try: @@ -447,9 +447,9 @@ _GL = lambda m: m and objects.S_ISGITLINK(m) if _GL(self._stat_modes.get(path)): tree = self.repository._repo[self._tree_id] - cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(tree['.gitmodules'][1]).data)) - url = cf.get(('submodule', path), 'url') - node = SubModuleNode(path, url=url, changeset=id_, + cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(tree[b'.gitmodules'][1]).data)) + url = ascii_str(cf.get(('submodule', path), 'url')) + node = SubModuleNode(path, url=url, changeset=ascii_str(id_), alias=self.repository.alias) else: obj = self.repository._repo.get_object(id_) @@ -465,7 +465,7 @@ node._blob = obj else: raise NodeDoesNotExistError("There is no file nor directory " - "at the given path '%s' at revision %s" + "at the given path: '%s' at revision %s" % (path, self.short_id)) # cache node self.nodes[path] = node @@ -480,16 +480,6 @@ return list(added.union(modified).union(deleted)) @LazyProperty - def _diff_name_status(self): - output = [] - for parent in self.parents: - cmd = ['diff', '--name-status', parent.raw_id, self.raw_id, - '--encoding=utf8'] - so, se = self.repository.run_git_command(cmd) - output.append(so.strip()) - return '\n'.join(output) - - @LazyProperty def _changes_cache(self): added = set() modified = set() @@ -503,15 +493,15 @@ if isinstance(parent, EmptyChangeset): oid = None else: - oid = _r[parent.raw_id].tree - changes = _r.object_store.tree_changes(oid, _r[self.raw_id].tree) + oid = _r[parent._commit.id].tree + changes = _r.object_store.tree_changes(oid, _r[self._commit.id].tree) for (oldpath, newpath), (_, _), (_, _) in changes: if newpath and oldpath: - modified.add(newpath) + modified.add(safe_str(newpath)) elif newpath and not oldpath: - added.add(newpath) + added.add(safe_str(newpath)) elif not newpath and oldpath: - deleted.add(oldpath) + deleted.add(safe_str(oldpath)) return added, modified, deleted def _get_paths_for_status(self, status): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/git/inmemory.py --- a/kallithea/lib/vcs/backends/git/inmemory.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/git/inmemory.py Thu Feb 06 01:19:23 2020 +0100 @@ -7,7 +7,7 @@ from kallithea.lib.vcs.backends.base import BaseInMemoryChangeset from kallithea.lib.vcs.exceptions import RepositoryError -from kallithea.lib.vcs.utils import safe_str +from kallithea.lib.vcs.utils import ascii_str, safe_bytes class GitInMemoryChangeset(BaseInMemoryChangeset): @@ -39,7 +39,7 @@ repo = self.repository._repo object_store = repo.object_store - ENCODING = "UTF-8" + ENCODING = b"UTF-8" # TODO: should probably be kept in sync with safe_str/safe_bytes and vcs/conf/settings.py DEFAULT_ENCODINGS # Create tree and populates it with blobs commit_tree = self.parents[0] and repo[self.parents[0]._commit.tree] or \ @@ -47,7 +47,7 @@ for node in self.added + self.changed: # Compute subdirs if needed dirpath, nodename = posixpath.split(node.path) - dirnames = map(safe_str, dirpath and dirpath.split('/') or []) + dirnames = safe_bytes(dirpath).split(b'/') if dirpath else [] parent = commit_tree ancestors = [('', parent)] @@ -68,13 +68,9 @@ # for dirnames (in reverse order) [this only applies for nodes from added] new_trees = [] - if not node.is_binary: - content = node.content.encode(ENCODING) - else: - content = node.content - blob = objects.Blob.from_string(content) + blob = objects.Blob.from_string(node.content) - node_path = node.name.encode(ENCODING) + node_path = safe_bytes(node.name) if dirnames: # If there are trees which should be created we need to build # them now (in reverse order) @@ -104,7 +100,7 @@ for tree in new_trees: object_store.add_object(tree) for node in self.removed: - paths = node.path.split('/') + paths = safe_bytes(node.path).split(b'/') tree = commit_tree trees = [tree] # Traverse deep into the forest... @@ -117,7 +113,7 @@ except KeyError: break # Cut down the blob and all rotten trees on the way back... - for path, tree in reversed(zip(paths, trees)): + for path, tree in reversed(list(zip(paths, trees))): del tree[path] if tree: # This tree still has elements - don't remove it or any @@ -130,9 +126,9 @@ commit = objects.Commit() commit.tree = commit_tree.id commit.parents = [p._commit.id for p in self.parents if p] - commit.author = commit.committer = safe_str(author) + commit.author = commit.committer = safe_bytes(author) commit.encoding = ENCODING - commit.message = safe_str(message) + commit.message = safe_bytes(message) # Compute date if date is None: @@ -150,11 +146,10 @@ object_store.add_object(commit) - ref = 'refs/heads/%s' % branch + # Update vcs repository object & recreate dulwich repo + ref = b'refs/heads/%s' % safe_bytes(branch) repo.refs[ref] = commit.id - - # Update vcs repository object & recreate dulwich repo - self.repository.revisions.append(commit.id) + self.repository.revisions.append(ascii_str(commit.id)) # invalidate parsed refs after commit self.repository._parsed_refs = self.repository._get_parsed_refs() tip = self.repository.get_changeset() @@ -177,15 +172,15 @@ return [] def get_tree_for_dir(tree, dirname): - for name, mode, id in tree.iteritems(): + for name, mode, id in tree.items(): if name == dirname: obj = self.repository._repo[id] if isinstance(obj, objects.Tree): return obj else: raise RepositoryError("Cannot create directory %s " - "at tree %s as path is occupied and is not a " - "Tree" % (dirname, tree)) + "at tree %s as path is occupied and is not a " + "Tree" % (dirname, tree)) return None trees = [] diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/git/repository.py --- a/kallithea/lib/vcs/backends/git/repository.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/git/repository.py Thu Feb 06 01:19:23 2020 +0100 @@ -12,13 +12,15 @@ import errno import logging import os -import posixpath import re import time -import urllib -import urllib2 +import urllib.error +import urllib.parse +import urllib.request from collections import OrderedDict +import mercurial.url # import httpbasicauthhandler, httpdigestauthhandler +import mercurial.util # import url as hg_url from dulwich.config import ConfigFile from dulwich.objects import Tag from dulwich.repo import NotGitRepository, Repo @@ -28,8 +30,7 @@ from kallithea.lib.vcs.conf import settings from kallithea.lib.vcs.exceptions import ( BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError, TagDoesNotExistError) -from kallithea.lib.vcs.utils import date_fromtimestamp, makedate, safe_str, safe_unicode -from kallithea.lib.vcs.utils.hgcompat import hg_url, httpbasicauthhandler, httpdigestauthhandler +from kallithea.lib.vcs.utils import ascii_str, date_fromtimestamp, makedate, safe_bytes, safe_str from kallithea.lib.vcs.utils.lazy import LazyProperty from kallithea.lib.vcs.utils.paths import abspath, get_user_home @@ -53,7 +54,7 @@ def __init__(self, repo_path, create=False, src_url=None, update_after_clone=False, bare=False): - self.path = safe_unicode(abspath(repo_path)) + self.path = abspath(repo_path) self.repo = self._get_repo(create, src_url, update_after_clone, bare) self.bare = self.repo.bare @@ -97,63 +98,54 @@ return self._get_all_revisions() @classmethod - def _run_git_command(cls, cmd, **opts): + def _run_git_command(cls, cmd, cwd=None): """ - Runs given ``cmd`` as git command and returns tuple - (stdout, stderr). + Runs given ``cmd`` as git command and returns output bytes in a tuple + (stdout, stderr) ... or raise RepositoryError. :param cmd: git command to be executed - :param opts: env options to pass into Subprocess command + :param cwd: passed directly to subprocess """ - - if '_bare' in opts: - _copts = [] - del opts['_bare'] - else: - _copts = ['-c', 'core.quotepath=false', ] - safe_call = False - if '_safe' in opts: - # no exc on failure - del opts['_safe'] - safe_call = True - - assert isinstance(cmd, list), cmd - - gitenv = os.environ # need to clean fix GIT_DIR ! - if 'GIT_DIR' in gitenv: - del gitenv['GIT_DIR'] + gitenv = dict(os.environ) + gitenv.pop('GIT_DIR', None) gitenv['GIT_CONFIG_NOGLOBAL'] = '1' - _git_path = settings.GIT_EXECUTABLE_PATH - cmd = [_git_path] + _copts + cmd + assert isinstance(cmd, list), cmd + cmd = [settings.GIT_EXECUTABLE_PATH, '-c', 'core.quotepath=false'] + cmd + try: + p = subprocessio.SubprocessIOChunker(cmd, cwd=cwd, env=gitenv, shell=False) + except (EnvironmentError, OSError) as err: + # output from the failing process is in str(EnvironmentError) + msg = ("Couldn't run git command %s.\n" + "Subprocess failed with '%s': %s\n" % + (cmd, type(err).__name__, err) + ).strip() + log.error(msg) + raise RepositoryError(msg) try: - _opts = dict( - env=gitenv, - shell=False, - ) - _opts.update(opts) - p = subprocessio.SubprocessIOChunker(cmd, **_opts) - except (EnvironmentError, OSError) as err: - tb_err = ("Couldn't run git command (%s).\n" - "Original error was:%s\n" % (cmd, err)) - log.error(tb_err) - if safe_call: - return '', err - else: - raise RepositoryError(tb_err) - - try: - return ''.join(p.output), ''.join(p.error) + stdout = b''.join(p.output) + stderr = b''.join(p.error) finally: p.close() + # TODO: introduce option to make commands fail if they have any stderr output? + if stderr: + log.debug('stderr from %s:\n%s', cmd, stderr) + else: + log.debug('stderr from %s: None', cmd) + return stdout, stderr def run_git_command(self, cmd): - opts = {} + """ + Runs given ``cmd`` as git command with cwd set to current repo. + Returns stdout as unicode str ... or raise RepositoryError. + """ + cwd = None if os.path.isdir(self.path): - opts['cwd'] = self.path - return self._run_git_command(cmd, **opts) + cwd = self.path + stdout, _stderr = self._run_git_command(cmd, cwd=cwd) + return safe_str(stdout) @classmethod def _check_url(cls, url): @@ -166,7 +158,6 @@ On failures it'll raise urllib2.HTTPError, exception is also thrown when the return code is non 200 """ - # check first if it's not an local url if os.path.isdir(url) or url.startswith('file:'): return True @@ -178,29 +169,30 @@ url = url[url.find('+') + 1:] handlers = [] - url_obj = hg_url(url) + url_obj = mercurial.util.url(safe_bytes(url)) test_uri, authinfo = url_obj.authinfo() - url_obj.passwd = '*****' - cleaned_uri = str(url_obj) - if not test_uri.endswith('info/refs'): test_uri = test_uri.rstrip('/') + '/info/refs' + url_obj.passwd = b'*****' + cleaned_uri = str(url_obj) + if authinfo: # create a password manager - passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() + passmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() passmgr.add_password(*authinfo) - handlers.extend((httpbasicauthhandler(passmgr), - httpdigestauthhandler(passmgr))) + handlers.extend((mercurial.url.httpbasicauthhandler(passmgr), + mercurial.url.httpdigestauthhandler(passmgr))) - o = urllib2.build_opener(*handlers) + o = urllib.request.build_opener(*handlers) o.addheaders = [('User-Agent', 'git/1.7.8.0')] # fake some git - q = {"service": 'git-upload-pack'} - qs = '?%s' % urllib.urlencode(q) - cu = "%s%s" % (test_uri, qs) - req = urllib2.Request(cu, None, {}) + req = urllib.request.Request( + "%s?%s" % ( + test_uri, + urllib.parse.urlencode({"service": 'git-upload-pack'}) + )) try: resp = o.open(req) @@ -208,13 +200,13 @@ raise Exception('Return Code is not 200') except Exception as e: # means it cannot be cloned - raise urllib2.URLError("[%s] org_exc: %s" % (cleaned_uri, e)) + raise urllib.error.URLError("[%s] org_exc: %s" % (cleaned_uri, e)) # now detect if it's proper git repo gitdata = resp.read() if 'service=git-upload-pack' not in gitdata: - raise urllib2.URLError( - "url [%s] does not look like an git" % (cleaned_uri)) + raise urllib.error.URLError( + "url [%s] does not look like an git" % cleaned_uri) return True @@ -253,7 +245,7 @@ rev_filter = settings.GIT_REV_FILTER cmd = ['rev-list', rev_filter, '--reverse', '--date-order'] try: - so, se = self.run_git_command(cmd) + so = self.run_git_command(cmd) except RepositoryError: # Can be raised for empty repositories return [] @@ -261,58 +253,56 @@ def _get_all_revisions2(self): # alternate implementation using dulwich - includes = [x[1][0] for x in self._parsed_refs.iteritems() - if x[1][1] != 'T'] + includes = [ascii_str(sha) for key, (sha, type_) in self._parsed_refs.items() + if type_ != b'T'] return [c.commit.id for c in self._repo.get_walker(include=includes)] def _get_revision(self, revision): """ - For git backend we always return integer here. This way we ensure - that changeset's revision attribute would become integer. + Given any revision identifier, returns a 40 char string with revision hash. """ - - is_null = lambda o: len(o) == revision.count('0') - if self._empty: raise EmptyRepositoryError("There are no changesets yet") if revision in (None, '', 'tip', 'HEAD', 'head', -1): - return self.revisions[-1] + revision = -1 - is_bstr = isinstance(revision, (str, unicode)) - if ((is_bstr and revision.isdigit() and len(revision) < 12) - or isinstance(revision, int) or is_null(revision) - ): + if isinstance(revision, int): try: - revision = self.revisions[int(revision)] + return self.revisions[revision] except IndexError: - msg = ("Revision %s does not exist for %s" % (revision, self)) + msg = "Revision %r does not exist for %s" % (revision, self.name) raise ChangesetDoesNotExistError(msg) - elif is_bstr: - # get by branch/tag name - _ref_revision = self._parsed_refs.get(revision) - if _ref_revision: # and _ref_revision[1] in ['H', 'RH', 'T']: - return _ref_revision[0] + if isinstance(revision, str): + if revision.isdigit() and (len(revision) < 12 or len(revision) == revision.count('0')): + try: + return self.revisions[int(revision)] + except IndexError: + msg = "Revision %r does not exist for %s" % (revision, self) + raise ChangesetDoesNotExistError(msg) - _tags_shas = self.tags.values() + # get by branch/tag name + _ref_revision = self._parsed_refs.get(safe_bytes(revision)) + if _ref_revision: # and _ref_revision[1] in [b'H', b'RH', b'T']: + return ascii_str(_ref_revision[0]) + + if revision in self.revisions: + return revision + # maybe it's a tag ? we don't have them in self.revisions - if revision in _tags_shas: - return _tags_shas[_tags_shas.index(revision)] + if revision in self.tags.values(): + return revision - elif not SHA_PATTERN.match(revision) or revision not in self.revisions: - msg = ("Revision %s does not exist for %s" % (revision, self)) + if SHA_PATTERN.match(revision): + msg = "Revision %r does not exist for %s" % (revision, self.name) raise ChangesetDoesNotExistError(msg) - # Ensure we return full id - if not SHA_PATTERN.match(str(revision)): - raise ChangesetDoesNotExistError("Given revision %s not recognized" - % revision) - return revision + raise ChangesetDoesNotExistError("Given revision %r not recognized" % revision) def get_ref_revision(self, ref_type, ref_name): """ - Returns ``MercurialChangeset`` object representing repository's + Returns ``GitChangeset`` object representing repository's changeset at the given ``revision``. """ return self._get_revision(ref_name) @@ -327,20 +317,10 @@ Returns normalized url. If schema is not given, would fall to filesystem (``file:///``) schema. """ - url = safe_str(url) if url != 'default' and '://' not in url: url = ':///'.join(('file', url)) return url - def get_hook_location(self): - """ - returns absolute path to location where hooks are stored - """ - loc = os.path.join(self.path, 'hooks') - if not self.bare: - loc = os.path.join(self.path, '.git', 'hooks') - return loc - @LazyProperty def name(self): return os.path.basename(self.path) @@ -367,9 +347,7 @@ @LazyProperty def description(self): - undefined_description = u'unknown' - _desc = self._repo.get_description() - return safe_unicode(_desc or undefined_description) + return safe_str(self._repo.get_description() or b'unknown') @LazyProperty def contact(self): @@ -381,8 +359,8 @@ if not self.revisions: return {} sortkey = lambda ctx: ctx[0] - _branches = [(x[0], x[1][0]) - for x in self._parsed_refs.iteritems() if x[1][1] == 'H'] + _branches = [(safe_str(key), ascii_str(sha)) + for key, (sha, type_) in self._parsed_refs.items() if type_ == b'H'] return OrderedDict(sorted(_branches, key=sortkey, reverse=False)) @LazyProperty @@ -398,8 +376,8 @@ return {} sortkey = lambda ctx: ctx[0] - _tags = [(x[0], x[1][0]) - for x in self._parsed_refs.iteritems() if x[1][1] == 'T'] + _tags = [(safe_str(key), ascii_str(sha)) + for key, (sha, type_) in self._parsed_refs.items() if type_ == b'T'] return OrderedDict(sorted(_tags, key=sortkey, reverse=True)) def tag(self, name, user, revision=None, message=None, date=None, @@ -420,7 +398,7 @@ changeset = self.get_changeset(revision) message = message or "Added tag %s for commit %s" % (name, changeset.raw_id) - self._repo.refs["refs/tags/%s" % name] = changeset._commit.id + self._repo.refs[b"refs/tags/%s" % safe_bytes(name)] = changeset._commit.id self._parsed_refs = self._get_parsed_refs() self.tags = self._get_tags() @@ -439,7 +417,8 @@ """ if name not in self.tags: raise TagDoesNotExistError("Tag %s does not exist" % name) - tagpath = posixpath.join(self._repo.refs.path, 'refs', 'tags', name) + # self._repo.refs is a DiskRefsContainer, and .path gives the full absolute path of '.git' + tagpath = os.path.join(safe_str(self._repo.refs.path), 'refs', 'tags', name) try: os.remove(tagpath) self._parsed_refs = self._get_parsed_refs() @@ -459,18 +438,20 @@ return self._get_parsed_refs() def _get_parsed_refs(self): - # cache the property + """Return refs as a dict, like: + { b'v0.2.0': [b'599ba911aa24d2981225f3966eb659dfae9e9f30', b'T'] } + """ _repo = self._repo refs = _repo.get_refs() - keys = [('refs/heads/', 'H'), - ('refs/remotes/origin/', 'RH'), - ('refs/tags/', 'T')] + keys = [(b'refs/heads/', b'H'), + (b'refs/remotes/origin/', b'RH'), + (b'refs/tags/', b'T')] _refs = {} - for ref, sha in refs.iteritems(): + for ref, sha in refs.items(): for k, type_ in keys: if ref.startswith(k): _key = ref[len(k):] - if type_ == 'T': + if type_ == b'T': obj = _repo.get_object(sha) if isinstance(obj, Tag): sha = _repo.get_object(sha).object[1] @@ -483,13 +464,13 @@ heads = {} for key, val in refs.items(): - for ref_key in ['refs/heads/', 'refs/remotes/origin/']: + for ref_key in [b'refs/heads/', b'refs/remotes/origin/']: if key.startswith(ref_key): n = key[len(ref_key):] - if n not in ['HEAD']: + if n not in [b'HEAD']: heads[n] = val - return heads if reverse else dict((y, x) for x, y in heads.iteritems()) + return heads if reverse else dict((y, x) for x, y in heads.items()) def get_changeset(self, revision=None): """ @@ -498,9 +479,7 @@ """ if isinstance(revision, GitChangeset): return revision - revision = self._get_revision(revision) - changeset = GitChangeset(repository=self, revision=revision) - return changeset + return GitChangeset(repository=self, revision=self._get_revision(revision)) def get_changesets(self, start=None, end=None, start_date=None, end_date=None, branch_name=None, reverse=False, max_revisions=None): @@ -547,7 +526,7 @@ else: cmd.append(settings.GIT_REV_FILTER) - revs = self.run_git_command(cmd)[0].splitlines() + revs = self.run_git_command(cmd).splitlines() start_pos = 0 end_pos = len(revs) if start: @@ -572,14 +551,15 @@ revs = revs[start_pos:end_pos] if reverse: - revs = reversed(revs) + revs.reverse() + return CollectionGenerator(self, revs) def get_diff(self, rev1, rev2, path=None, ignore_whitespace=False, context=3): """ - Returns (git like) *diff*, as plain text. Shows changes introduced by - ``rev2`` since ``rev1``. + Returns (git like) *diff*, as plain bytes text. Shows changes + introduced by ``rev2`` since ``rev1``. :param rev1: Entry point from which diff is shown. Can be ``self.EMPTY_CHANGESET`` - in this case, patch showing all @@ -633,14 +613,13 @@ if path: cmd += ['--', path] - stdout, stderr = self.run_git_command(cmd) - # TODO: don't ignore stderr + stdout, stderr = self._run_git_command(cmd, cwd=self.path) # If we used 'show' command, strip first few lines (until actual diff # starts) if rev1 == self.EMPTY_CHANGESET: - parts = stdout.split('\ndiff ', 1) + parts = stdout.split(b'\ndiff ', 1) if len(parts) > 1: - stdout = 'diff ' + parts[1] + stdout = b'diff ' + parts[1] return stdout @LazyProperty @@ -683,7 +662,7 @@ Tries to pull changes from external location. """ url = self._get_url(url) - so, se = self.run_git_command(['ls-remote', '-h', url]) + so = self.run_git_command(['ls-remote', '-h', url]) cmd = ['fetch', url, '--'] for line in (x for x in so.splitlines()): sha, ref = line.split('\t') @@ -721,7 +700,7 @@ """ if config_file is None: config_file = [] - elif isinstance(config_file, basestring): + elif isinstance(config_file, str): config_file = [config_file] def gen_configs(): @@ -733,9 +712,10 @@ for config in gen_configs(): try: - return config.get(section, name) + value = config.get(section, name) except KeyError: continue + return None if value is None else safe_str(value) return None def get_user_name(self, config_file=None): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/git/ssh.py --- a/kallithea/lib/vcs/backends/git/ssh.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/git/ssh.py Thu Feb 06 01:19:23 2020 +0100 @@ -17,7 +17,6 @@ from kallithea.lib.hooks import log_pull_action from kallithea.lib.utils import make_ui -from kallithea.lib.utils2 import safe_str, safe_unicode from kallithea.lib.vcs.backends.ssh import BaseSshHandler @@ -33,15 +32,15 @@ >>> import shlex >>> GitSshHandler.make(shlex.split("git-upload-pack '/foo bar'")).repo_name - u'foo bar' + 'foo bar' >>> GitSshHandler.make(shlex.split("git-upload-pack '/foo bar'")).verb 'git-upload-pack' >>> GitSshHandler.make(shlex.split(" git-upload-pack /blåbærgrød ")).repo_name # might not be necessary to support no quoting ... but we can - u'bl\xe5b\xe6rgr\xf8d' + 'bl\xe5b\xe6rgr\xf8d' >>> GitSshHandler.make(shlex.split('''git-upload-pack "/foo'bar"''')).repo_name - u"foo'bar" + "foo'bar" >>> GitSshHandler.make(shlex.split("git-receive-pack '/foo'")).repo_name - u'foo' + 'foo' >>> GitSshHandler.make(shlex.split("git-receive-pack '/foo'")).verb 'git-receive-pack' @@ -56,12 +55,12 @@ ssh_command_parts[0] in ['git-upload-pack', 'git-receive-pack'] and ssh_command_parts[1].startswith('/') ): - return cls(safe_unicode(ssh_command_parts[1][1:]), ssh_command_parts[0]) + return cls(ssh_command_parts[1][1:], ssh_command_parts[0]) return None def __init__(self, repo_name, verb): - self.repo_name = repo_name + BaseSshHandler.__init__(self, repo_name) self.verb = verb def _serve(self): @@ -70,7 +69,7 @@ log_pull_action(ui=make_ui(), repo=self.db_repo.scm_instance._repo) else: # probably verb 'git-receive-pack', action 'push' if not self.allow_push: - self.exit('Push access to %r denied' % safe_str(self.repo_name)) + self.exit('Push access to %r denied' % self.repo_name) # Note: push logging is handled by Git post-receive hook # git shell is not a real shell but use shell inspired quoting *inside* the argument. diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/git/workdir.py --- a/kallithea/lib/vcs/backends/git/workdir.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/git/workdir.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,5 +1,6 @@ import re +from kallithea.lib.utils2 import ascii_str, safe_str from kallithea.lib.vcs.backends.base import BaseWorkdir from kallithea.lib.vcs.exceptions import BranchDoesNotExistError, RepositoryError @@ -7,9 +8,9 @@ class GitWorkdir(BaseWorkdir): def get_branch(self): - headpath = self.repository._repo.refs.refpath('HEAD') + headpath = self.repository._repo.refs.refpath(b'HEAD') try: - content = open(headpath).read() + content = safe_str(open(headpath, 'rb').read()) match = re.match(r'^ref: refs/heads/(?P.+)\n$', content) if match: return match.groupdict()['branch'] @@ -20,7 +21,7 @@ raise RepositoryError("Couldn't compute workdir's branch") def get_changeset(self): - wk_dir_id = self.repository._repo.refs.as_dict().get('HEAD') + wk_dir_id = ascii_str(self.repository._repo.refs.as_dict().get(b'HEAD')) return self.repository.get_changeset(wk_dir_id) def checkout_branch(self, branch=None): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/hg/__init__.py --- a/kallithea/lib/vcs/backends/hg/__init__.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/hg/__init__.py Thu Feb 06 01:19:23 2020 +0100 @@ -9,6 +9,8 @@ :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak. """ +from kallithea.lib.vcs.utils import hgcompat + from .changeset import MercurialChangeset from .inmemory import MercurialInMemoryChangeset from .repository import MercurialRepository @@ -19,3 +21,5 @@ 'MercurialRepository', 'MercurialChangeset', 'MercurialInMemoryChangeset', 'MercurialWorkdir', ] + +hgcompat.monkey_do() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/hg/changeset.py --- a/kallithea/lib/vcs/backends/hg/changeset.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/hg/changeset.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,41 +1,44 @@ import os import posixpath +import mercurial.archival +import mercurial.node +import mercurial.obsutil + from kallithea.lib.vcs.backends.base import BaseChangeset from kallithea.lib.vcs.conf import settings from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, ChangesetError, ImproperArchiveTypeError, NodeDoesNotExistError, VCSError from kallithea.lib.vcs.nodes import ( AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode, SubModuleNode) -from kallithea.lib.vcs.utils import date_fromtimestamp, safe_str, safe_unicode -from kallithea.lib.vcs.utils.hgcompat import archival, hex, obsutil +from kallithea.lib.vcs.utils import ascii_bytes, ascii_str, date_fromtimestamp, safe_bytes, safe_str from kallithea.lib.vcs.utils.lazy import LazyProperty from kallithea.lib.vcs.utils.paths import get_dirs_for_path class MercurialChangeset(BaseChangeset): """ - Represents state of the repository at the single revision. + Represents state of the repository at a revision. """ def __init__(self, repository, revision): self.repository = repository - assert isinstance(revision, basestring), repr(revision) - self.raw_id = revision - self._ctx = repository._repo[revision] + assert isinstance(revision, str), repr(revision) + self._ctx = repository._repo[ascii_bytes(revision)] + self.raw_id = ascii_str(self._ctx.hex()) self.revision = self._ctx._rev self.nodes = {} @LazyProperty def tags(self): - return map(safe_unicode, self._ctx.tags()) + return [safe_str(tag) for tag in self._ctx.tags()] @LazyProperty def branch(self): - return safe_unicode(self._ctx.branch()) + return safe_str(self._ctx.branch()) @LazyProperty def branches(self): - return [safe_unicode(self._ctx.branch())] + return [safe_str(self._ctx.branch())] @LazyProperty def closesbranch(self): @@ -47,17 +50,11 @@ @LazyProperty def bumped(self): - try: - return self._ctx.phasedivergent() - except AttributeError: # renamed in Mercurial 4.6 (9fa874fb34e1) - return self._ctx.bumped() + return self._ctx.phasedivergent() @LazyProperty def divergent(self): - try: - return self._ctx.contentdivergent() - except AttributeError: # renamed in Mercurial 4.6 (8b2d7684407b) - return self._ctx.divergent() + return self._ctx.contentdivergent() @LazyProperty def extinct(self): @@ -65,10 +62,7 @@ @LazyProperty def unstable(self): - try: - return self._ctx.orphan() - except AttributeError: # renamed in Mercurial 4.6 (03039ff3082b) - return self._ctx.unstable() + return self._ctx.orphan() @LazyProperty def phase(self): @@ -81,33 +75,33 @@ @LazyProperty def successors(self): - successors = obsutil.successorssets(self._ctx._repo, self._ctx.node(), closest=True) + successors = mercurial.obsutil.successorssets(self._ctx._repo, self._ctx.node(), closest=True) if successors: # flatten the list here handles both divergent (len > 1) # and the usual case (len = 1) - successors = [hex(n)[:12] for sub in successors for n in sub if n != self._ctx.node()] + successors = [mercurial.node.hex(n)[:12] for sub in successors for n in sub if n != self._ctx.node()] return successors @LazyProperty def predecessors(self): - return [hex(n)[:12] for n in obsutil.closestpredecessors(self._ctx._repo, self._ctx.node())] + return [mercurial.node.hex(n)[:12] for n in mercurial.obsutil.closestpredecessors(self._ctx._repo, self._ctx.node())] @LazyProperty def bookmarks(self): - return map(safe_unicode, self._ctx.bookmarks()) + return [safe_str(bookmark) for bookmark in self._ctx.bookmarks()] @LazyProperty def message(self): - return safe_unicode(self._ctx.description()) + return safe_str(self._ctx.description()) @LazyProperty def committer(self): - return safe_unicode(self.author) + return safe_str(self.author) @LazyProperty def author(self): - return safe_unicode(self._ctx.user()) + return safe_str(self._ctx.user()) @LazyProperty def date(self): @@ -127,7 +121,7 @@ @LazyProperty def _file_paths(self): - return list(self._ctx) + return list(safe_str(f) for f in self._ctx) @LazyProperty def _dir_paths(self): @@ -140,12 +134,6 @@ return self._dir_paths + self._file_paths @LazyProperty - def id(self): - if self.last: - return u'tip' - return self.short_id - - @LazyProperty def short_id(self): return self.raw_id[:12] @@ -202,8 +190,8 @@ return cs def diff(self): - # Only used for feed diffstat - return ''.join(self._ctx.diff()) + # Only used to feed diffstat + return b''.join(self._ctx.diff()) def _fix_path(self, path): """ @@ -214,7 +202,7 @@ if path.endswith('/'): path = path.rstrip('/') - return safe_str(path) + return path def _get_kind(self, path): path = self._fix_path(path) @@ -231,7 +219,7 @@ if self._get_kind(path) != NodeKind.FILE: raise ChangesetError("File does not exist for revision %s at " " '%s'" % (self.raw_id, path)) - return self._ctx.filectx(path) + return self._ctx.filectx(safe_bytes(path)) def _extract_submodules(self): """ @@ -245,10 +233,10 @@ Returns stat mode of the file at the given ``path``. """ fctx = self._get_filectx(path) - if 'x' in fctx.flags(): - return 0100755 + if b'x' in fctx.flags(): + return 0o100755 else: - return 0100644 + return 0o100644 def get_file_content(self, path): """ @@ -280,7 +268,7 @@ cnt = 0 for cs in reversed([x for x in fctx.filelog()]): cnt += 1 - hist.append(hex(fctx.filectx(cs).node())) + hist.append(mercurial.node.hex(fctx.filectx(cs).node())) if limit is not None and cnt == limit: break @@ -292,13 +280,10 @@ lineno, sha, changeset lazy loader and line """ annotations = self._get_filectx(path).annotate() - try: - annotation_lines = [(annotateline.fctx, annotateline.text) for annotateline in annotations] - except AttributeError: # annotateline was introduced in Mercurial 4.6 (b33b91ca2ec2) - annotation_lines = [(aline.fctx, l) for aline, l in annotations] - for i, (fctx, l) in enumerate(annotation_lines): - sha = fctx.hex() - yield (i + 1, sha, lambda sha=sha, l=l: self.repository.get_changeset(sha), l) + annotation_lines = [(annotateline.fctx, annotateline.text) for annotateline in annotations] + for i, (fctx, line) in enumerate(annotation_lines): + sha = ascii_str(fctx.hex()) + yield (i + 1, sha, lambda sha=sha: self.repository.get_changeset(sha), line) def fill_archive(self, stream=None, kind='tgz', prefix=None, subrepos=False): @@ -316,11 +301,10 @@ :raise ImproperArchiveTypeError: If given kind is wrong. :raise VcsError: If given stream is None """ - - allowed_kinds = settings.ARCHIVE_SPECS.keys() + allowed_kinds = settings.ARCHIVE_SPECS if kind not in allowed_kinds: raise ImproperArchiveTypeError('Archive kind not supported use one' - 'of %s' % allowed_kinds) + 'of %s' % ' '.join(allowed_kinds)) if stream is None: raise VCSError('You need to pass in a valid stream for filling' @@ -333,8 +317,8 @@ elif prefix.strip() == '': raise VCSError("Prefix cannot be empty") - archival.archive(self.repository._repo, stream, self.raw_id, - kind, prefix=prefix, subrepos=subrepos) + mercurial.archival.archive(self.repository._repo, stream, ascii_bytes(self.raw_id), + safe_bytes(kind), prefix=safe_bytes(prefix), subrepos=subrepos) def get_nodes(self, path): """ @@ -356,18 +340,16 @@ if os.path.dirname(d) == path] als = self.repository.alias - for k, vals in self._extract_submodules().iteritems(): + for k, vals in self._extract_submodules().items(): #vals = url,rev,type loc = vals[0] cs = vals[1] dirnodes.append(SubModuleNode(k, url=loc, changeset=cs, alias=als)) nodes = dirnodes + filenodes - # cache nodes for node in nodes: self.nodes[node.path] = node nodes.sort() - return nodes def get_node(self, path): @@ -375,9 +357,7 @@ Returns ``Node`` object from the given ``path``. If there is no node at the given ``path``, ``ChangesetError`` would be raised. """ - path = self._fix_path(path) - if path not in self.nodes: if path in self._file_paths: node = FileNode(path, changeset=self) @@ -406,21 +386,21 @@ """ Returns list of added ``FileNode`` objects. """ - return AddedFileNodesGenerator([n for n in self.status[1]], self) + return AddedFileNodesGenerator([safe_str(n) for n in self.status.added], self) @property def changed(self): """ Returns list of modified ``FileNode`` objects. """ - return ChangedFileNodesGenerator([n for n in self.status[0]], self) + return ChangedFileNodesGenerator([safe_str(n) for n in self.status.modified], self) @property def removed(self): """ Returns list of removed ``FileNode`` objects. """ - return RemovedFileNodesGenerator([n for n in self.status[2]], self) + return RemovedFileNodesGenerator([safe_str(n) for n in self.status.removed], self) @LazyProperty def extra(self): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/hg/inmemory.py --- a/kallithea/lib/vcs/backends/hg/inmemory.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/hg/inmemory.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,14 +1,17 @@ import datetime +import mercurial.context +import mercurial.node + from kallithea.lib.vcs.backends.base import BaseInMemoryChangeset from kallithea.lib.vcs.exceptions import RepositoryError -from kallithea.lib.vcs.utils.hgcompat import hex, memctx, memfilectx, tolocal +from kallithea.lib.vcs.utils import ascii_str, safe_bytes, safe_str class MercurialInMemoryChangeset(BaseInMemoryChangeset): def commit(self, message, author, parents=None, branch=None, date=None, - **kwargs): + **kwargs): """ Performs in-memory commit (doesn't check workdir in any way) and returns newly created ``Changeset``. Updates repository's @@ -27,21 +30,22 @@ """ self.check_integrity(parents) + if not isinstance(message, str): + raise RepositoryError('message must be a str - got %r' % type(message)) + if not isinstance(author, str): + raise RepositoryError('author must be a str - got %r' % type(author)) + from .repository import MercurialRepository - if not isinstance(message, unicode) or not isinstance(author, unicode): - raise RepositoryError('Given message and author needs to be ' - 'an instance got %r & %r instead' - % (type(message), type(author))) - if branch is None: branch = MercurialRepository.DEFAULT_BRANCH_NAME - kwargs['branch'] = branch + kwargs[b'branch'] = safe_bytes(branch) - def filectxfn(_repo, memctx, path): + def filectxfn(_repo, memctx, bytes_path): """ - Marks given path as added/changed/removed in a given _repo. This is - for internal mercurial commit function. + Callback from Mercurial, returning ctx to commit for the given + path. """ + path = safe_str(bytes_path) # check if this path is removed if path in (node.path for node in self.removed): @@ -50,9 +54,8 @@ # check if this path is added for node in self.added: if node.path == path: - return memfilectx(_repo, memctx, path=node.path, - data=(node.content.encode('utf-8') - if not node.is_binary else node.content), + return mercurial.context.memfilectx(_repo, memctx, path=bytes_path, + data=node.content, islink=False, isexec=node.is_executable, copysource=False) @@ -60,14 +63,13 @@ # or changed for node in self.changed: if node.path == path: - return memfilectx(_repo, memctx, path=node.path, - data=(node.content.encode('utf-8') - if not node.is_binary else node.content), + return mercurial.context.memfilectx(_repo, memctx, path=bytes_path, + data=node.content, islink=False, isexec=node.is_executable, copysource=False) - raise RepositoryError("Given path haven't been marked as added," + raise RepositoryError("Given path haven't been marked as added, " "changed or removed (%s)" % path) parents = [None, None] @@ -76,22 +78,21 @@ parents[i] = parent._ctx.node() if date and isinstance(date, datetime.datetime): - date = date.strftime('%a, %d %b %Y %H:%M:%S') + date = safe_bytes(date.strftime('%a, %d %b %Y %H:%M:%S')) - commit_ctx = memctx(repo=self.repository._repo, + commit_ctx = mercurial.context.memctx( + repo=self.repository._repo, parents=parents, - text='', - files=self.get_paths(), + text=b'', + files=[safe_bytes(x) for x in self.get_paths()], filectxfn=filectxfn, - user=author, + user=safe_bytes(author), date=date, extra=kwargs) - loc = lambda u: tolocal(u.encode('utf-8')) - # injecting given _repo params - commit_ctx._text = loc(message) - commit_ctx._user = loc(author) + commit_ctx._text = safe_bytes(message) + commit_ctx._user = safe_bytes(author) commit_ctx._date = date # TODO: Catch exceptions! @@ -100,9 +101,8 @@ self._commit_ctx = commit_ctx # For reference # Update vcs repository object & recreate mercurial _repo # new_ctx = self.repository._repo[node] - # new_tip = self.repository.get_changeset(new_ctx.hex()) - new_id = hex(n) - self.repository.revisions.append(new_id) + # new_tip = ascii_str(self.repository.get_changeset(new_ctx.hex())) + self.repository.revisions.append(ascii_str(mercurial.node.hex(n))) self._repo = self.repository._get_repo(create=False) self.repository.branches = self.repository._get_branches() tip = self.repository.get_changeset() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/hg/repository.py --- a/kallithea/lib/vcs/backends/hg/repository.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/hg/repository.py Thu Feb 06 01:19:23 2020 +0100 @@ -13,16 +13,33 @@ import logging import os import time -import urllib -import urllib2 +import urllib.error +import urllib.parse +import urllib.request from collections import OrderedDict +import mercurial.commands +import mercurial.error +import mercurial.exchange +import mercurial.hg +import mercurial.hgweb +import mercurial.httppeer +import mercurial.localrepo +import mercurial.match +import mercurial.mdiff +import mercurial.node +import mercurial.patch +import mercurial.scmutil +import mercurial.sshpeer +import mercurial.tags +import mercurial.ui +import mercurial.url +import mercurial.util + from kallithea.lib.vcs.backends.base import BaseRepository, CollectionGenerator from kallithea.lib.vcs.exceptions import ( BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError, TagDoesNotExistError, VCSError) -from kallithea.lib.vcs.utils import author_email, author_name, date_fromtimestamp, makedate, safe_str, safe_unicode -from kallithea.lib.vcs.utils.hgcompat import ( - Abort, RepoError, RepoLookupError, clone, diffopts, get_contact, hex, hg_url, httpbasicauthhandler, httpdigestauthhandler, httppeer, localrepo, match_exact, nullid, patch, peer, scmutil, sshpeer, tag, ui) +from kallithea.lib.vcs.utils import ascii_str, author_email, author_name, date_fromtimestamp, makedate, safe_bytes, safe_str from kallithea.lib.vcs.utils.lazy import LazyProperty from kallithea.lib.vcs.utils.paths import abspath @@ -60,9 +77,8 @@ raise VCSError('Mercurial backend requires repository path to ' 'be instance of got %s instead' % type(repo_path)) - self.path = abspath(repo_path) - self.baseui = baseui or ui.ui() + self.baseui = baseui or mercurial.ui.ui() # We've set path and ui, now we can set _repo itself self._repo = self._get_repo(create, src_url, update_after_clone) @@ -115,14 +131,13 @@ return {} bt = OrderedDict() - for bn, _heads, tip, isclosed in sorted(self._repo.branchmap().iterbranches()): + for bn, _heads, node, isclosed in sorted(self._repo.branchmap().iterbranches()): if isclosed: if closed: - bt[safe_unicode(bn)] = hex(tip) + bt[safe_str(bn)] = ascii_str(mercurial.node.hex(node)) else: if normal: - bt[safe_unicode(bn)] = hex(tip) - + bt[safe_str(bn)] = ascii_str(mercurial.node.hex(node)) return bt @LazyProperty @@ -136,11 +151,11 @@ if self._empty: return {} - sortkey = lambda ctx: ctx[0] # sort by name - _tags = [(safe_unicode(n), hex(h),) for n, h in - self._repo.tags().items()] - - return OrderedDict(sorted(_tags, key=sortkey, reverse=True)) + return OrderedDict(sorted( + ((safe_str(n), ascii_str(mercurial.node.hex(h))) for n, h in self._repo.tags().items()), + reverse=True, + key=lambda x: x[0], # sort by name + )) def tag(self, name, user, revision=None, message=None, date=None, **kwargs): @@ -165,12 +180,12 @@ changeset.short_id) if date is None: - date = datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S') + date = safe_bytes(datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S')) try: - tag(self._repo, name, changeset._ctx.node(), message, local, user, date) - except Abort as e: - raise RepositoryError(e.message) + mercurial.tags.tag(self._repo, safe_bytes(name), changeset._ctx.node(), safe_bytes(message), local, safe_bytes(user), date) + except mercurial.error.Abort as e: + raise RepositoryError(e.args[0]) # Reinitialize tags self.tags = self._get_tags() @@ -194,14 +209,14 @@ if message is None: message = "Removed tag %s" % name if date is None: - date = datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S') + date = safe_bytes(datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S')) local = False try: - tag(self._repo, name, nullid, message, local, user, date) + mercurial.tags.tag(self._repo, safe_bytes(name), mercurial.commands.nullid, safe_bytes(message), local, safe_bytes(user), date) self.tags = self._get_tags() - except Abort as e: - raise RepositoryError(e.message) + except mercurial.error.Abort as e: + raise RepositoryError(e.args[0]) @LazyProperty def bookmarks(self): @@ -214,14 +229,14 @@ if self._empty: return {} - sortkey = lambda ctx: ctx[0] # sort by name - _bookmarks = [(safe_unicode(n), hex(h),) for n, h in - self._repo._bookmarks.items()] - return OrderedDict(sorted(_bookmarks, key=sortkey, reverse=True)) + return OrderedDict(sorted( + ((safe_str(n), ascii_str(h)) for n, h in self._repo._bookmarks.items()), + reverse=True, + key=lambda x: x[0], # sort by name + )) def _get_all_revisions(self): - - return [self._repo[x].hex() for x in self._repo.filtered('visible').changelog.revs()] + return [ascii_str(self._repo[x].hex()) for x in self._repo.filtered(b'visible').changelog.revs()] def get_diff(self, rev1, rev2, path='', ignore_whitespace=False, context=3): @@ -257,12 +272,12 @@ self.get_changeset(rev1) self.get_changeset(rev2) if path: - file_filter = match_exact(path) + file_filter = mercurial.match.exact(path) else: file_filter = None - return ''.join(patch.diff(self._repo, rev1, rev2, match=file_filter, - opts=diffopts(git=True, + return b''.join(mercurial.patch.diff(self._repo, rev1, rev2, match=file_filter, + opts=mercurial.mdiff.diffopts(git=True, showfunc=True, ignorews=ignore_whitespace, context=context))) @@ -279,42 +294,45 @@ when the return code is non 200 """ # check first if it's not an local url - if os.path.isdir(url) or url.startswith('file:'): + if os.path.isdir(url) or url.startswith(b'file:'): return True - if url.startswith('ssh:'): + if url.startswith(b'ssh:'): # in case of invalid uri or authentication issues, sshpeer will # throw an exception. - sshpeer.instance(repoui or ui.ui(), url, False).lookup('tip') + mercurial.sshpeer.instance(repoui or mercurial.ui.ui(), url, False).lookup(b'tip') return True url_prefix = None - if '+' in url[:url.find('://')]: - url_prefix, url = url.split('+', 1) + if b'+' in url[:url.find(b'://')]: + url_prefix, url = url.split(b'+', 1) handlers = [] - url_obj = hg_url(url) + url_obj = mercurial.util.url(url) test_uri, authinfo = url_obj.authinfo() - url_obj.passwd = '*****' + url_obj.passwd = b'*****' cleaned_uri = str(url_obj) if authinfo: # create a password manager - passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() + passmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() passmgr.add_password(*authinfo) - handlers.extend((httpbasicauthhandler(passmgr), - httpdigestauthhandler(passmgr))) + handlers.extend((mercurial.url.httpbasicauthhandler(passmgr), + mercurial.url.httpdigestauthhandler(passmgr))) - o = urllib2.build_opener(*handlers) + o = urllib.request.build_opener(*handlers) o.addheaders = [('Content-Type', 'application/mercurial-0.1'), ('Accept', 'application/mercurial-0.1')] - q = {"cmd": 'between'} - q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)}) - qs = '?%s' % urllib.urlencode(q) - cu = "%s%s" % (test_uri, qs) - req = urllib2.Request(cu, None, {}) + req = urllib.request.Request( + "%s?%s" % ( + test_uri, + urllib.parse.urlencode({ + 'cmd': 'between', + 'pairs': "%s-%s" % ('0' * 40, '0' * 40), + }) + )) try: resp = o.open(req) @@ -322,14 +340,14 @@ raise Exception('Return Code is not 200') except Exception as e: # means it cannot be cloned - raise urllib2.URLError("[%s] org_exc: %s" % (cleaned_uri, e)) + raise urllib.error.URLError("[%s] org_exc: %s" % (cleaned_uri, e)) if not url_prefix: # skip svn+http://... (and git+... too) # now check if it's a proper hg repo try: - httppeer.instance(repoui or ui.ui(), url, False).lookup('tip') + mercurial.httppeer.instance(repoui or mercurial.ui.ui(), url, False).lookup(b'tip') except Exception as e: - raise urllib2.URLError( + raise urllib.error.URLError( "url [%s] does not look like an hg repo org_exc: %s" % (cleaned_uri, e)) @@ -345,26 +363,25 @@ location at given clone_point. Additionally it'll make update to working copy accordingly to ``update_after_clone`` flag """ - try: if src_url: - url = safe_str(self._get_url(src_url)) + url = safe_bytes(self._get_url(src_url)) opts = {} if not update_after_clone: opts.update({'noupdate': True}) MercurialRepository._check_url(url, self.baseui) - clone(self.baseui, url, self.path, **opts) + mercurial.commands.clone(self.baseui, url, safe_bytes(self.path), **opts) # Don't try to create if we've already cloned repo create = False - return localrepo.instance(self.baseui, self.path, create=create) - except (Abort, RepoError) as err: + return mercurial.localrepo.instance(self.baseui, safe_bytes(self.path), create=create) + except (mercurial.error.Abort, mercurial.error.RepoError) as err: if create: msg = "Cannot create repository at %s. Original error was %s" \ - % (self.path, err) + % (self.name, err) else: msg = "Not valid repository at %s. Original error was %s" \ - % (self.path, err) + % (self.name, err) raise RepositoryError(msg) @LazyProperty @@ -373,15 +390,13 @@ @LazyProperty def description(self): - undefined_description = u'unknown' - _desc = self._repo.ui.config('web', 'description', None, untrusted=True) - return safe_unicode(_desc or undefined_description) + _desc = self._repo.ui.config(b'web', b'description', None, untrusted=True) + return safe_str(_desc or b'unknown') @LazyProperty def contact(self): - undefined_contact = u'Unknown' - return safe_unicode(get_contact(self._repo.ui.config) - or undefined_contact) + return safe_str(mercurial.hgweb.common.get_contact(self._repo.ui.config) + or b'Unknown') @LazyProperty def last_change(self): @@ -404,39 +419,33 @@ def _get_revision(self, revision): """ - Gets an ID revision given as str. This will always return a full - 40 char revision number + Given any revision identifier, returns a 40 char string with revision hash. :param revision: str or int or None """ - if isinstance(revision, unicode): - revision = safe_str(revision) - if self._empty: raise EmptyRepositoryError("There are no changesets yet") if revision in [-1, None]: - revision = 'tip' + revision = b'tip' + elif isinstance(revision, str): + revision = safe_bytes(revision) try: if isinstance(revision, int): - return self._repo[revision].hex() - try: - return scmutil.revsymbol(self._repo, revision).hex() - except AttributeError: # revsymbol was introduced in Mercurial 4.6 - return self._repo[revision].hex() - except (IndexError, ValueError, RepoLookupError, TypeError): - msg = ("Revision %s does not exist for %s" % (revision, self)) + return ascii_str(self._repo[revision].hex()) + return ascii_str(mercurial.scmutil.revsymbol(self._repo, revision).hex()) + except (IndexError, ValueError, mercurial.error.RepoLookupError, TypeError): + msg = "Revision %r does not exist for %s" % (safe_str(revision), self.name) raise ChangesetDoesNotExistError(msg) except (LookupError, ): - msg = ("Ambiguous identifier `%s` for %s" % (revision, self)) + msg = "Ambiguous identifier `%s` for %s" % (safe_str(revision), self.name) raise ChangesetDoesNotExistError(msg) def get_ref_revision(self, ref_type, ref_name): """ Returns revision number for the given reference. """ - ref_name = safe_str(ref_name) if ref_type == 'rev' and not ref_name.strip('0'): return self.EMPTY_CHANGESET # lookup up the exact node id @@ -451,17 +460,13 @@ try: revs = self._repo.revs(rev_spec, ref_name, ref_name) except LookupError: - msg = ("Ambiguous identifier %s:%s for %s" % (ref_type, ref_name, self.name)) + msg = "Ambiguous identifier %s:%s for %s" % (ref_type, ref_name, self.name) raise ChangesetDoesNotExistError(msg) - except RepoLookupError: - msg = ("Revision %s:%s does not exist for %s" % (ref_type, ref_name, self.name)) + except mercurial.error.RepoLookupError: + msg = "Revision %s:%s does not exist for %s" % (ref_type, ref_name, self.name) raise ChangesetDoesNotExistError(msg) if revs: - try: - revision = revs.last() - except AttributeError: - # removed in hg 3.2 - revision = revs[-1] + revision = revs.last() else: # TODO: just report 'not found'? revision = ref_name @@ -469,39 +474,29 @@ return self._get_revision(revision) def _get_archives(self, archive_name='tip'): - allowed = self.baseui.configlist("web", "allow_archive", + allowed = self.baseui.configlist(b"web", b"allow_archive", untrusted=True) - for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]: - if i[0] in allowed or self._repo.ui.configbool("web", - "allow" + i[0], + for name, ext in [(b'zip', '.zip'), (b'gz', '.tar.gz'), (b'bz2', '.tar.bz2')]: + if name in allowed or self._repo.ui.configbool(b"web", + b"allow" + name, untrusted=True): - yield {"type": i[0], "extension": i[1], "node": archive_name} + yield {"type": safe_str(name), "extension": ext, "node": archive_name} def _get_url(self, url): """ - Returns normalized url. If schema is not given, would fall - to filesystem - (``file:///``) schema. + Returns normalized url. If schema is not given, fall back to + filesystem (``file:///``) schema. """ - url = safe_str(url) if url != 'default' and '://' not in url: - url = "file:" + urllib.pathname2url(url) + url = "file:" + urllib.request.pathname2url(url) return url - def get_hook_location(self): - """ - returns absolute path to location where hooks are stored - """ - return os.path.join(self.path, '.hg', '.hgrc') - def get_changeset(self, revision=None): """ Returns ``MercurialChangeset`` object representing repository's changeset at the given ``revision``. """ - revision = self._get_revision(revision) - changeset = MercurialChangeset(repository=self, revision=revision) - return changeset + return MercurialChangeset(repository=self, revision=self._get_revision(revision)) def get_changesets(self, start=None, end=None, start_date=None, end_date=None, branch_name=None, reverse=False, max_revisions=None): @@ -517,35 +512,35 @@ :param reversed: return changesets in reversed order """ start_raw_id = self._get_revision(start) - start_pos = self.revisions.index(start_raw_id) if start else None + start_pos = None if start is None else self.revisions.index(start_raw_id) end_raw_id = self._get_revision(end) - end_pos = self.revisions.index(end_raw_id) if end else None + end_pos = None if end is None else self.revisions.index(end_raw_id) - if None not in [start, end] and start_pos > end_pos: + if start_pos is not None and end_pos is not None and start_pos > end_pos: raise RepositoryError("Start revision '%s' cannot be " "after end revision '%s'" % (start, end)) - if branch_name and branch_name not in self.allbranches.keys(): - msg = ("Branch %s not found in %s" % (branch_name, self)) + if branch_name and branch_name not in self.allbranches: + msg = "Branch %r not found in %s" % (branch_name, self.name) raise BranchDoesNotExistError(msg) if end_pos is not None: end_pos += 1 # filter branches filter_ = [] if branch_name: - filter_.append('branch("%s")' % safe_str(branch_name)) + filter_.append(b'branch("%s")' % safe_bytes(branch_name)) if start_date: - filter_.append('date(">%s")' % start_date) + filter_.append(b'date(">%s")' % safe_bytes(str(start_date))) if end_date: - filter_.append('date("<%s")' % end_date) + filter_.append(b'date("<%s")' % safe_bytes(str(end_date))) if filter_ or max_revisions: if filter_: - revspec = ' and '.join(filter_) + revspec = b' and '.join(filter_) else: - revspec = 'all()' + revspec = b'all()' if max_revisions: - revspec = 'limit(%s, %s)' % (revspec, max_revisions) - revisions = scmutil.revrange(self._repo, [revspec]) + revspec = b'limit(%s, %d)' % (revspec, max_revisions) + revisions = mercurial.scmutil.revrange(self._repo, [revspec]) else: revisions = self.revisions @@ -553,7 +548,7 @@ # would be to get rid of this function entirely and use revsets revs = list(revisions)[start_pos:end_pos] if reverse: - revs = reversed(revs) + revs.reverse() return CollectionGenerator(self, revs) @@ -561,15 +556,10 @@ """ Tries to pull changes from external location. """ - url = self._get_url(url) - other = peer(self._repo, {}, url) + other = mercurial.hg.peer(self._repo, {}, safe_bytes(self._get_url(url))) try: - # hg 3.2 moved push / pull to exchange module - from mercurial import exchange - exchange.pull(self._repo, other, heads=None, force=None) - except ImportError: - self._repo.pull(other, heads=None, force=None) - except Abort as err: + mercurial.exchange.pull(self._repo, other, heads=None, force=None) + except mercurial.error.Abort as err: # Propagate error but with vcs's type raise RepositoryError(str(err)) @@ -591,15 +581,16 @@ """ if config_file is None: config_file = [] - elif isinstance(config_file, basestring): + elif isinstance(config_file, str): config_file = [config_file] config = self._repo.ui if config_file: - config = ui.ui() + config = mercurial.ui.ui() for path in config_file: - config.readconfig(path) - return config.config(section, name) + config.readconfig(safe_bytes(path)) + value = config.config(safe_bytes(section), safe_bytes(name)) + return value if value is None else safe_str(value) def get_user_name(self, config_file=None): """ diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/hg/ssh.py --- a/kallithea/lib/vcs/backends/hg/ssh.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/hg/ssh.py Thu Feb 06 01:19:23 2020 +0100 @@ -14,18 +14,12 @@ import logging -from mercurial import hg +import mercurial.hg +import mercurial.wireprotoserver from kallithea.lib.utils import make_ui -from kallithea.lib.utils2 import safe_str, safe_unicode from kallithea.lib.vcs.backends.ssh import BaseSshHandler - - -try: - from mercurial.wireprotoserver import sshserver -except ImportError: - from mercurial.sshserver import sshserver # moved in Mercurial 4.6 (1bf5263fe5cc) - +from kallithea.lib.vcs.utils import safe_bytes log = logging.getLogger(__name__) @@ -40,11 +34,11 @@ >>> import shlex >>> MercurialSshHandler.make(shlex.split('hg -R "foo bar" serve --stdio')).repo_name - u'foo bar' + 'foo bar' >>> MercurialSshHandler.make(shlex.split(' hg -R blåbærgrød serve --stdio ')).repo_name - u'bl\xe5b\xe6rgr\xf8d' + 'bl\xe5b\xe6rgr\xf8d' >>> MercurialSshHandler.make(shlex.split('''hg -R 'foo"bar' serve --stdio''')).repo_name - u'foo"bar' + 'foo"bar' >>> MercurialSshHandler.make(shlex.split('/bin/hg -R "foo" serve --stdio')) >>> MercurialSshHandler.make(shlex.split('''hg -R "foo"bar" serve --stdio''')) # ssh-serve will report: Error parsing SSH command "...": invalid syntax @@ -53,20 +47,17 @@ >>> MercurialSshHandler.make(shlex.split('git-upload-pack "/foo"')) # not handled here """ if ssh_command_parts[:2] == ['hg', '-R'] and ssh_command_parts[3:] == ['serve', '--stdio']: - return cls(safe_unicode(ssh_command_parts[2])) + return cls(ssh_command_parts[2]) return None - def __init__(self, repo_name): - self.repo_name = repo_name - def _serve(self): # Note: we want a repo with config based on .hg/hgrc and can thus not use self.db_repo.scm_instance._repo.ui baseui = make_ui(repo_path=self.db_repo.repo_full_path) if not self.allow_push: - baseui.setconfig('hooks', 'pretxnopen._ssh_reject', 'python:kallithea.lib.hooks.rejectpush') - baseui.setconfig('hooks', 'prepushkey._ssh_reject', 'python:kallithea.lib.hooks.rejectpush') + baseui.setconfig(b'hooks', b'pretxnopen._ssh_reject', b'python:kallithea.lib.hooks.rejectpush') + baseui.setconfig(b'hooks', b'prepushkey._ssh_reject', b'python:kallithea.lib.hooks.rejectpush') - repo = hg.repository(baseui, safe_str(self.db_repo.repo_full_path)) + repo = mercurial.hg.repository(baseui, safe_bytes(self.db_repo.repo_full_path)) log.debug("Starting Mercurial sshserver for %s", self.db_repo.repo_full_path) - sshserver(baseui, repo).serve_forever() + mercurial.wireprotoserver.sshserver(baseui, repo).serve_forever() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/hg/workdir.py --- a/kallithea/lib/vcs/backends/hg/workdir.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/hg/workdir.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,15 +1,17 @@ +import mercurial.merge + from kallithea.lib.vcs.backends.base import BaseWorkdir from kallithea.lib.vcs.exceptions import BranchDoesNotExistError -from kallithea.lib.vcs.utils.hgcompat import hg_merge +from kallithea.lib.vcs.utils import ascii_bytes, ascii_str, safe_str class MercurialWorkdir(BaseWorkdir): def get_branch(self): - return self.repository._repo.dirstate.branch() + return safe_str(self.repository._repo.dirstate.branch()) def get_changeset(self): - wk_dir_id = self.repository._repo[None].parents()[0].hex() + wk_dir_id = ascii_str(self.repository._repo[None].parents()[0].hex()) return self.repository.get_changeset(wk_dir_id) def checkout_branch(self, branch=None): @@ -19,4 +21,4 @@ raise BranchDoesNotExistError raw_id = self.repository.branches[branch] - hg_merge.update(self.repository._repo, raw_id, False, False, None) + mercurial.merge.update(self.repository._repo, ascii_bytes(raw_id), False, False, None) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/backends/ssh.py --- a/kallithea/lib/vcs/backends/ssh.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/backends/ssh.py Thu Feb 06 01:19:23 2020 +0100 @@ -24,7 +24,7 @@ import sys from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware -from kallithea.lib.utils2 import safe_str, set_hook_environment +from kallithea.lib.utils2 import set_hook_environment from kallithea.model.db import Repository, User, UserSshKeys from kallithea.model.meta import Session @@ -55,6 +55,9 @@ """ raise NotImplementedError + def __init__(self, repo_name): + self.repo_name = repo_name.rstrip('/') + def serve(self, user_id, key_id, client_ip): """Verify basic sanity of the repository, and that the user is valid and has access - then serve the native VCS protocol for @@ -79,7 +82,7 @@ elif HasPermissionAnyMiddleware('repository.read')(self.authuser, self.repo_name): self.allow_push = False else: - self.exit('Access to %r denied' % safe_str(self.repo_name)) + self.exit('Access to %r denied' % self.repo_name) self.db_repo = Repository.get_by_repo_name(self.repo_name) if self.db_repo is None: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/conf/settings.py --- a/kallithea/lib/vcs/conf/settings.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/conf/settings.py Thu Feb 06 01:19:23 2020 +0100 @@ -18,7 +18,7 @@ if os.path.isdir(VCSRC_PATH): VCSRC_PATH = os.path.join(VCSRC_PATH, '__init__.py') -# list of default encoding used in safe_unicode/safe_str methods +# list of default encoding used in safe_str/safe_bytes methods DEFAULT_ENCODINGS = aslist('utf-8') # path to git executable run by run_git_command function diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/nodes.py --- a/kallithea/lib/vcs/nodes.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/nodes.py Thu Feb 06 01:19:23 2020 +0100 @@ -9,13 +9,14 @@ :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak. """ +import functools import mimetypes import posixpath import stat from kallithea.lib.vcs.backends.base import EmptyChangeset from kallithea.lib.vcs.exceptions import NodeError, RemovedFileNodeError -from kallithea.lib.vcs.utils import safe_str, safe_unicode +from kallithea.lib.vcs.utils import safe_bytes, safe_str from kallithea.lib.vcs.utils.lazy import LazyProperty @@ -44,11 +45,9 @@ self.cs = cs self.current_paths = current_paths - def __call__(self): - return [n for n in self] - - def __getslice__(self, i, j): - for p in self.current_paths[i:j]: + def __getitem__(self, key): + assert isinstance(key, slice), key + for p in self.current_paths[key]: yield self.cs.get_node(p) def __len__(self): @@ -81,11 +80,13 @@ for p in self.current_paths: yield RemovedFileNode(path=p) - def __getslice__(self, i, j): - for p in self.current_paths[i:j]: + def __getitem__(self, key): + assert isinstance(key, slice), key + for p in self.current_paths[key]: yield RemovedFileNode(path=p) +@functools.total_ordering class Node(object): """ Simplest class representing file or directory on repository. SCM backends @@ -101,7 +102,7 @@ if path.startswith('/'): raise NodeError("Cannot initialize Node objects with slash at " "the beginning as only relative paths are supported") - self.path = safe_str(path.rstrip('/')) # we store paths as str + self.path = path.rstrip('/') if path == '' and kind != NodeKind.DIR: raise NodeError("Only DirNode and its subclasses may be " "initialized with empty path") @@ -120,16 +121,12 @@ return None @LazyProperty - def unicode_path(self): - return safe_unicode(self.path) - - @LazyProperty def name(self): """ Returns name of the node so if its path then only last part is returned. """ - return safe_unicode(self.path.rstrip('/').split('/')[-1]) + return self.path.rstrip('/').split('/')[-1] def _get_kind(self): return self._kind @@ -145,42 +142,41 @@ kind = property(_get_kind, _set_kind) - def __cmp__(self, other): - """ - Comparator using name of the node, needed for quick list sorting. - """ - kind_cmp = cmp(self.kind, other.kind) - if kind_cmp: - return kind_cmp - return cmp(self.name, other.name) - def __eq__(self, other): - for attr in ['name', 'path', 'kind']: - if getattr(self, attr) != getattr(other, attr): - return False + if type(self) is not type(other): + return False + if self._kind != other._kind: + return False + if self.path != other.path: + return False if self.is_file(): - if self.content != other.content: - return False + return self.content == other.content else: # For DirNode's check without entering each dir self_nodes_paths = list(sorted(n.path for n in self.nodes)) other_nodes_paths = list(sorted(n.path for n in self.nodes)) - if self_nodes_paths != other_nodes_paths: - return False - return True + return self_nodes_paths == other_nodes_paths - def __nq__(self, other): - return not self.__eq__(other) + def __lt__(self, other): + if self._kind < other._kind: + return True + if self._kind > other._kind: + return False + if self.path < other.path: + return True + if self.path > other.path: + return False + if self.is_file(): + return self.content < other.content + else: + # For DirNode's check without entering each dir + self_nodes_paths = list(sorted(n.path for n in self.nodes)) + other_nodes_paths = list(sorted(n.path for n in self.nodes)) + return self_nodes_paths < other_nodes_paths def __repr__(self): return '<%s %r>' % (self.__class__.__name__, self.path) - def __str__(self): - return self.__repr__() - - def __unicode__(self): - return self.name - def get_parent_path(self): """ Returns node's parent path or empty string if node is root. @@ -258,8 +254,12 @@ raise NodeError("Cannot use both content and changeset") super(FileNode, self).__init__(path, kind=NodeKind.FILE) self.changeset = changeset + if not isinstance(content, bytes) and content is not None: + # File content is one thing that inherently must be bytes ... but + # VCS module tries to be "user friendly" and support unicode ... + content = safe_bytes(content) self._content = content - self._mode = mode or 0100644 + self._mode = mode or 0o100644 @LazyProperty def mode(self): @@ -273,25 +273,17 @@ mode = self._mode return mode - def _get_content(self): + @property + def content(self): + """ + Returns lazily byte content of the FileNode. + """ if self.changeset: content = self.changeset.get_file_content(self.path) else: content = self._content return content - @property - def content(self): - """ - Returns lazily content of the FileNode. If possible, would try to - decode content from UTF-8. - """ - content = self._get_content() - - if bool(content and '\0' in content): - return content - return safe_unicode(content) - @LazyProperty def size(self): if self.changeset: @@ -329,8 +321,8 @@ encoding = None # try with pygments + from pygments import lexers try: - from pygments import lexers mt = lexers.get_lexer_for_filename(self.name).mimetypes except lexers.ClassNotFound: mt = None @@ -361,7 +353,7 @@ """ from pygments import lexers try: - lexer = lexers.guess_lexer_for_filename(self.name, self.content, stripnl=False) + lexer = lexers.guess_lexer_for_filename(self.name, safe_str(self.content), stripnl=False) except lexers.ClassNotFound: lexer = lexers.TextLexer(stripnl=False) # returns first alias @@ -409,8 +401,7 @@ """ Returns True if file has binary content. """ - _bin = '\0' in self._get_content() - return _bin + return b'\0' in self.content def is_browser_compatible_image(self): return self.mimetype in [ @@ -595,12 +586,13 @@ size = 0 def __init__(self, name, url, changeset=None, alias=None): + # Note: Doesn't call Node.__init__! self.path = name self.kind = NodeKind.SUBMODULE self.alias = alias # we have to use emptyChangeset here since this can point to svn/git/hg # submodules we cannot get from repository - self.changeset = EmptyChangeset(str(changeset), alias=alias) + self.changeset = EmptyChangeset(changeset, alias=alias) self.url = url def __repr__(self): @@ -613,5 +605,5 @@ Returns name of the node so if its path then only last part is returned. """ - org = safe_unicode(self.path.rstrip('/').split('/')[-1]) + org = self.path.rstrip('/').rsplit('/', 1)[-1] return u'%s @ %s' % (org, self.changeset.short_id) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/subprocessio.py --- a/kallithea/lib/vcs/subprocessio.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/subprocessio.py Thu Feb 06 01:19:23 2020 +0100 @@ -44,7 +44,7 @@ if type(source) in (type(''), bytes, bytearray): # string-like self.bytes = bytes(source) else: # can be either file pointer or file-like - if type(source) in (int, long): # file pointer it is + if isinstance(source, int): # file pointer it is # converting file descriptor (int) stdin into file-like source = os.fdopen(source, 'rb', 16384) # let's see if source is file-like by now @@ -125,11 +125,7 @@ if len(t) > ccm: kr.clear() kr.wait(2) - # # this only works on 2.7.x and up - # if not kr.wait(10): - # raise Exception("Timed out while waiting for input to be read.") - # instead we'll use this - if len(t) > ccm + 3: + if not kr.wait(10): raise IOError( "Timed out while waiting for input from subprocess.") t.append(b) @@ -178,7 +174,7 @@ def __iter__(self): return self - def next(self): + def __next__(self): while not len(self.data) and not self.worker.EOF.is_set(): self.worker.data_added.clear() self.worker.data_added.wait(0.2) @@ -286,7 +282,7 @@ - We are multithreaded. Writing in and reading out, err are all sep threads. - We support concurrent (in and out) stream processing. - - The output is not a stream. It's a queue of read string (bytes, not unicode) + - The output is not a stream. It's a queue of read string (bytes, not str) chunks. The object behaves as an iterable. You can "for chunk in obj:" us. - We are non-blocking in more respects than communicate() (reading from subprocess out pauses when internal buffer is full, but @@ -367,18 +363,17 @@ and returncode != 0 ): # and it failed bg_out.stop() - out = ''.join(bg_out) + out = b''.join(bg_out) bg_err.stop() - err = ''.join(bg_err) - if (err.strip() == 'fatal: The remote end hung up unexpectedly' and - out.startswith('0034shallow ') + err = b''.join(bg_err) + if (err.strip() == b'fatal: The remote end hung up unexpectedly' and + out.startswith(b'0034shallow ') ): # hack inspired by https://github.com/schacon/grack/pull/7 bg_out = iter([out]) _p = None elif err: - raise EnvironmentError( - "Subprocess exited due to an error:\n" + err) + raise EnvironmentError("Subprocess exited due to an error: %s" % err) else: raise EnvironmentError( "Subprocess exited with non 0 ret code: %s" % returncode) @@ -390,7 +385,7 @@ def __iter__(self): return self - def next(self): + def __next__(self): if self.process: returncode = self.process.poll() if (returncode is not None # process has terminated @@ -400,7 +395,7 @@ self.error.stop() err = ''.join(self.error) raise EnvironmentError("Subprocess exited due to an error:\n" + err) - return self.output.next() + return next(self.output) def throw(self, type, value=None, traceback=None): if self.output.length or not self.output.done_reading: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/utils/__init__.py --- a/kallithea/lib/vcs/utils/__init__.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/utils/__init__.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + """ This module provides some useful tools for ``vcs`` like annotate/diff html output. It also includes some internal helpers. @@ -25,7 +27,7 @@ :param sep: :param strip: """ - if isinstance(obj, (basestring)): + if isinstance(obj, str): lst = obj.split(sep) if strip: lst = [v.strip() for v in lst] @@ -66,89 +68,107 @@ return val -def safe_unicode(str_, from_encoding=None): +def safe_str(s): """ - safe unicode function. Does few trick to turn str_ into unicode - - In case of UnicodeDecode error we try to return it with encoding detected - by chardet library if it fails fallback to unicode with errors replaced - - :param str_: string to decode - :rtype: unicode - :returns: unicode object + Safe unicode str function. Use a few tricks to turn s into str: + In case of UnicodeDecodeError with configured default encodings, try to + detect encoding with chardet library, then fall back to first encoding with + errors replaced. """ - if isinstance(str_, unicode): - return str_ + if isinstance(s, str): + return s - if not from_encoding: - from kallithea.lib.vcs.conf import settings - from_encoding = settings.DEFAULT_ENCODINGS - - if not isinstance(from_encoding, (list, tuple)): - from_encoding = [from_encoding] + if not isinstance(s, bytes): # use __str__ and don't expect UnicodeDecodeError + return str(s) - try: - return unicode(str_) - except UnicodeDecodeError: - pass - - for enc in from_encoding: + from kallithea.lib.vcs.conf import settings + for enc in settings.DEFAULT_ENCODINGS: try: - return unicode(str_, enc) + return str(s, enc) except UnicodeDecodeError: pass try: import chardet - encoding = chardet.detect(str_)['encoding'] - if encoding is None: - raise Exception() - return str_.decode(encoding) - except (ImportError, UnicodeDecodeError, Exception): - return unicode(str_, from_encoding[0], 'replace') + encoding = chardet.detect(s)['encoding'] + if encoding is not None: + return s.decode(encoding) + except (ImportError, UnicodeDecodeError): + pass + + return str(s, settings.DEFAULT_ENCODINGS[0], 'replace') -def safe_str(unicode_, to_encoding=None): +def safe_bytes(s): """ - safe str function. Does few trick to turn unicode_ into string - - In case of UnicodeEncodeError we try to return it with encoding detected - by chardet library if it fails fallback to string with errors replaced - - :param unicode_: unicode to encode - :rtype: str - :returns: str object + Safe bytes function. Use a few tricks to turn s into bytes string: + In case of UnicodeEncodeError with configured default encodings, fall back + to first configured encoding with errors replaced. """ + if isinstance(s, bytes): + return s - # if it's not basestr cast to str - if not isinstance(unicode_, basestring): - return str(unicode_) - - if isinstance(unicode_, str): - return unicode_ + assert isinstance(s, str), repr(s) # bytes cannot coerse with __str__ or handle None or int - if not to_encoding: - from kallithea.lib.vcs.conf import settings - to_encoding = settings.DEFAULT_ENCODINGS - - if not isinstance(to_encoding, (list, tuple)): - to_encoding = [to_encoding] - - for enc in to_encoding: + from kallithea.lib.vcs.conf import settings + for enc in settings.DEFAULT_ENCODINGS: try: - return unicode_.encode(enc) + return s.encode(enc) except UnicodeEncodeError: pass - try: - import chardet - encoding = chardet.detect(unicode_)['encoding'] - if encoding is None: - raise UnicodeEncodeError() + return s.encode(settings.DEFAULT_ENCODINGS[0], 'replace') + + +def ascii_bytes(s): + """ + Simple conversion from str to bytes, *assuming* all codepoints are + 7-bit and it thus is pure ASCII. + Will fail badly with UnicodeError on invalid input. + This should be used where enocding and "safe" ambiguity should be avoided. + Where strings already have been encoded in other ways but still are unicode + string - for example to hex, base64, json, urlencoding, or are known to be + identifiers. - return unicode_.encode(encoding) - except (ImportError, UnicodeEncodeError): - return unicode_.encode(to_encoding[0], 'replace') + >>> ascii_bytes('a') + b'a' + >>> ascii_bytes(u'a') + b'a' + >>> ascii_bytes('å') + Traceback (most recent call last): + UnicodeEncodeError: 'ascii' codec can't encode character '\xe5' in position 0: ordinal not in range(128) + >>> ascii_bytes('å'.encode('utf8')) + Traceback (most recent call last): + AssertionError: b'\xc3\xa5' + """ + assert isinstance(s, str), repr(s) + return s.encode('ascii') + + +def ascii_str(s): + r""" + Simple conversion from bytes to str, *assuming* all codepoints are + 7-bit and it thus is pure ASCII. + Will fail badly with UnicodeError on invalid input. + This should be used where enocding and "safe" ambiguity should be avoided. + Where strings are encoded but also in other ways are known to be ASCII, and + where a unicode string is wanted without caring about encoding. For example + to hex, base64, urlencoding, or are known to be identifiers. + + >>> ascii_str(b'a') + 'a' + >>> ascii_str(u'a') + Traceback (most recent call last): + AssertionError: 'a' + >>> ascii_str('å'.encode('utf8')) + Traceback (most recent call last): + UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128) + >>> ascii_str(u'å') + Traceback (most recent call last): + AssertionError: 'å' + """ + assert isinstance(s, bytes), repr(s) + return s.decode('ascii') # Regex taken from http://www.regular-expressions.info/email.html @@ -178,7 +198,7 @@ m = email_re.search(author) if m is None: return '' - return safe_str(m.group(0)) + return m.group(0) def author_name(author): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/utils/annotate.py --- a/kallithea/lib/vcs/utils/annotate.py Sun Jan 05 01:19:05 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -import StringIO - -from pygments import highlight -from pygments.formatters import HtmlFormatter - -from kallithea.lib.vcs.exceptions import VCSError -from kallithea.lib.vcs.nodes import FileNode - - -def annotate_highlight(filenode, annotate_from_changeset_func=None, - order=None, headers=None, **options): - """ - Returns html portion containing annotated table with 3 columns: line - numbers, changeset information and pygmentized line of code. - - :param filenode: FileNode object - :param annotate_from_changeset_func: function taking changeset and - returning single annotate cell; needs break line at the end - :param order: ordered sequence of ``ls`` (line numbers column), - ``annotate`` (annotate column), ``code`` (code column); Default is - ``['ls', 'annotate', 'code']`` - :param headers: dictionary with headers (keys are whats in ``order`` - parameter) - """ - options['linenos'] = True - formatter = AnnotateHtmlFormatter(filenode=filenode, order=order, - headers=headers, - annotate_from_changeset_func=annotate_from_changeset_func, **options) - lexer = filenode.lexer - highlighted = highlight(filenode.content, lexer, formatter) - return highlighted - - -class AnnotateHtmlFormatter(HtmlFormatter): - - def __init__(self, filenode, annotate_from_changeset_func=None, - order=None, **options): - """ - If ``annotate_from_changeset_func`` is passed it should be a function - which returns string from the given changeset. For example, we may pass - following function as ``annotate_from_changeset_func``:: - - def changeset_to_anchor(changeset): - return '%s\n' % \ - (changeset.id, changeset.id) - - :param annotate_from_changeset_func: see above - :param order: (default: ``['ls', 'annotate', 'code']``); order of - columns; - :param options: standard pygment's HtmlFormatter options, there is - extra option tough, ``headers``. For instance we can pass:: - - formatter = AnnotateHtmlFormatter(filenode, headers={ - 'ls': '#', - 'annotate': 'Annotate', - 'code': 'Code', - }) - - """ - super(AnnotateHtmlFormatter, self).__init__(**options) - self.annotate_from_changeset_func = annotate_from_changeset_func - self.order = order or ('ls', 'annotate', 'code') - headers = options.pop('headers', None) - if headers and not ('ls' in headers and 'annotate' in headers and - 'code' in headers - ): - raise ValueError("If headers option dict is specified it must " - "all 'ls', 'annotate' and 'code' keys") - self.headers = headers - if isinstance(filenode, FileNode): - self.filenode = filenode - else: - raise VCSError("This formatter expect FileNode parameter, not %r" - % type(filenode)) - - def annotate_from_changeset(self, changeset): - """ - Returns full html line for single changeset per annotated line. - """ - if self.annotate_from_changeset_func: - return self.annotate_from_changeset_func(changeset) - else: - return ''.join((changeset.id, '\n')) - - def _wrap_tablelinenos(self, inner): - dummyoutfile = StringIO.StringIO() - lncount = 0 - for t, line in inner: - if t: - lncount += 1 - dummyoutfile.write(line) - - fl = self.linenostart - mw = len(str(lncount + fl - 1)) - sp = self.linenospecial - st = self.linenostep - la = self.lineanchors - aln = self.anchorlinenos - if sp: - lines = [] - - for i in range(fl, fl + lncount): - if i % st == 0: - if i % sp == 0: - if aln: - lines.append('' - '%*d' % - (la, i, mw, i)) - else: - lines.append('' - '%*d' % (mw, i)) - else: - if aln: - lines.append('' - '%*d' % (la, i, mw, i)) - else: - lines.append('%*d' % (mw, i)) - else: - lines.append('') - ls = '\n'.join(lines) - else: - lines = [] - for i in range(fl, fl + lncount): - if i % st == 0: - if aln: - lines.append('%*d' - % (la, i, mw, i)) - else: - lines.append('%*d' % (mw, i)) - else: - lines.append('') - ls = '\n'.join(lines) - - annotate_changesets = [tup[1] for tup in self.filenode.annotate] - # If pygments cropped last lines break we need do that too - ln_cs = len(annotate_changesets) - ln_ = len(ls.splitlines()) - if ln_cs > ln_: - annotate_changesets = annotate_changesets[:ln_ - ln_cs] - annotate = ''.join((self.annotate_from_changeset(changeset) - for changeset in annotate_changesets)) - # in case you wonder about the seemingly redundant
    here: - # since the content in the other cell also is wrapped in a div, - # some browsers in some configurations seem to mess up the formatting. - ''' - yield 0, ('' % self.cssclass + - '' + - '
    ' +
    -                  ls + '
    ') - yield 0, dummyoutfile.getvalue() - yield 0, '
    ' - - ''' - headers_row = [] - if self.headers: - headers_row = [''] - for key in self.order: - td = ''.join(('', self.headers[key], '')) - headers_row.append(td) - headers_row.append('') - - body_row_start = [''] - for key in self.order: - if key == 'ls': - body_row_start.append( - '
    ' +
    -                    ls + '
    ') - elif key == 'annotate': - body_row_start.append( - '
    ' +
    -                    annotate + '
    ') - elif key == 'code': - body_row_start.append('') - yield 0, ('' % self.cssclass + - ''.join(headers_row) + - ''.join(body_row_start) - ) - yield 0, dummyoutfile.getvalue() - yield 0, '
    ' diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/utils/archivers.py --- a/kallithea/lib/vcs/utils/archivers.py Sun Jan 05 01:19:05 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -""" - vcs.utils.archivers - ~~~~~~~~~~~~~~~~~~~ - - set of archiver functions for creating archives from repository content - - :created_on: Jan 21, 2011 - :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak. -""" - - -class BaseArchiver(object): - - def __init__(self): - self.archive_file = self._get_archive_file() - - def addfile(self): - """ - Adds a file to archive container - """ - pass - - def close(self): - """ - Closes and finalizes operation of archive container object - """ - self.archive_file.close() - - def _get_archive_file(self): - """ - Returns container for specific archive - """ - raise NotImplementedError() - - -class TarArchiver(BaseArchiver): - pass - - -class Tbz2Archiver(BaseArchiver): - pass - - -class TgzArchiver(BaseArchiver): - pass - - -class ZipArchiver(BaseArchiver): - pass - - -def get_archiver(self, kind): - """ - Returns instance of archiver class specific to given kind - - :param kind: archive kind - """ - - archivers = { - 'tar': TarArchiver, - 'tbz2': Tbz2Archiver, - 'tgz': TgzArchiver, - 'zip': ZipArchiver, - } - - return archivers[kind]() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/utils/fakemod.py --- a/kallithea/lib/vcs/utils/fakemod.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/utils/fakemod.py Thu Feb 06 01:19:23 2020 +0100 @@ -9,5 +9,5 @@ """ module = imp.new_module(name) module.__file__ = path - execfile(path, module.__dict__) + exec(compile(open(path, "rb").read(), path, 'exec'), module.__dict__) return module diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/utils/helpers.py --- a/kallithea/lib/vcs/utils/helpers.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/utils/helpers.py Thu Feb 06 01:19:23 2020 +0100 @@ -33,16 +33,14 @@ if not os.path.isdir(path): raise VCSError("Given path %s is not a directory" % path) - def get_scms(path): - return [(scm, path) for scm in get_scms_for_path(path)] - - found_scms = get_scms(path) - while not found_scms and search_up: + while True: + found_scms = [(scm, path) for scm in get_scms_for_path(path)] + if found_scms or not search_up: + break newpath = abspath(path, '..') if newpath == path: break path = newpath - found_scms = get_scms(path) if len(found_scms) > 1: for scm in found_scms: @@ -133,7 +131,7 @@ >>> parse_changesets('aaabbb') {'start': None, 'main': 'aaabbb', 'end': None} >>> parse_changesets('aaabbb..cccddd') - {'start': 'aaabbb', 'main': None, 'end': 'cccddd'} + {'start': 'aaabbb', 'end': 'cccddd', 'main': None} """ text = text.strip() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/utils/hgcompat.py --- a/kallithea/lib/vcs/utils/hgcompat.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/utils/hgcompat.py Thu Feb 06 01:19:23 2020 +0100 @@ -2,46 +2,12 @@ Mercurial libs compatibility """ -# Mercurial 5.0 550a172a603b renamed memfilectx argument `copied` to `copysource` -import inspect - -import mercurial -from mercurial import archival, config, demandimport, discovery, httppeer, localrepo -from mercurial import merge as hg_merge -from mercurial import obsutil, patch, scmutil, sshpeer, ui, unionrepo -from mercurial.commands import clone, nullid, pull -from mercurial.context import memctx, memfilectx -from mercurial.discovery import findcommonoutgoing -from mercurial.encoding import tolocal -from mercurial.error import Abort, RepoError, RepoLookupError -from mercurial.hg import peer -from mercurial.hgweb import hgweb_mod -from mercurial.hgweb.common import get_contact -from mercurial.match import exact as match_exact -from mercurial.match import match -from mercurial.mdiff import diffopts -from mercurial.node import hex, nullrev -from mercurial.scmutil import revrange -from mercurial.tags import tag -from mercurial.url import httpbasicauthhandler, httpdigestauthhandler -from mercurial.util import url as hg_url +import mercurial.localrepo -# patch demandimport, due to bug in mercurial when it always triggers demandimport.enable() -demandimport.enable = lambda *args, **kwargs: 1 - - -# workaround for 3.3 94ac64bcf6fe and not calling largefiles reposetup correctly -localrepo.localrepository._lfstatuswriters = [lambda *msg, **opts: None] -# 3.5 7699d3212994 added the invariant that repo.lfstatus must exist before hitting overridearchive -localrepo.localrepository.lfstatus = False - -if inspect.getargspec(memfilectx.__init__).args[7] != 'copysource': - assert inspect.getargspec(memfilectx.__init__).args[7] == 'copied', inspect.getargspec(memfilectx.__init__).args - __org_memfilectx_ = memfilectx - memfilectx = lambda repo, changectx, path, data, islink=False, isexec=False, copysource=None: \ - __org_memfilectx_(repo, changectx, path, data, islink=islink, isexec=isexec, copied=copysource) - -# Mercurial 5.0 dropped exact argument for match in 635a12c53ea6, and 0531dff73d0b made the exact function stable with a single parameter -if inspect.getargspec(match_exact).args[0] != 'files': - match_exact = lambda path: match(None, '', [path], exact=True) +def monkey_do(): + """Apply some Mercurial monkey patching""" + # workaround for 3.3 94ac64bcf6fe and not calling largefiles reposetup correctly, and test_archival failing + mercurial.localrepo.localrepository._lfstatuswriters = [lambda *msg, **opts: None] + # 3.5 7699d3212994 added the invariant that repo.lfstatus must exist before hitting overridearchive + mercurial.localrepo.localrepository.lfstatus = False diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/utils/progressbar.py --- a/kallithea/lib/vcs/utils/progressbar.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/utils/progressbar.py Thu Feb 06 01:19:23 2020 +0100 @@ -43,7 +43,7 @@ def __iter__(self): start = self.step end = self.steps + 1 - for x in xrange(start, end): + for x in range(start, end): self.render(x) yield x @@ -215,7 +215,7 @@ code_list = [] if text == '' and len(opts) == 1 and opts[0] == 'reset': return '\x1b[%sm' % RESET - for k, v in kwargs.iteritems(): + for k, v in kwargs.items(): if k == 'fg': code_list.append(foreground[v]) elif k == 'bg': @@ -359,7 +359,7 @@ print("Standard progress bar...") bar = ProgressBar(30) - for x in xrange(1, 31): + for x in range(1, 31): bar.render(x) time.sleep(0.02) bar.stream.write('\n') @@ -410,7 +410,7 @@ bar.width = 50 bar.elements.remove('steps') bar.elements += ['transfer', 'time', 'eta', 'speed'] - for x in xrange(0, bar.steps, 1024): + for x in range(0, bar.steps, 1024): bar.render(x) time.sleep(0.01) now = datetime.datetime.now() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/lib/vcs/utils/termcolors.py --- a/kallithea/lib/vcs/utils/termcolors.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/lib/vcs/utils/termcolors.py Thu Feb 06 01:19:23 2020 +0100 @@ -44,7 +44,7 @@ code_list = [] if text == '' and len(opts) == 1 and opts[0] == 'reset': return '\x1b[%sm' % RESET - for k, v in kwargs.iteritems(): + for k, v in kwargs.items(): if k == 'fg': code_list.append(foreground[v]) elif k == 'bg': @@ -188,7 +188,7 @@ definition['bg'] = colors[-1] # All remaining instructions are options - opts = tuple(s for s in styles if s in opt_dict.keys()) + opts = tuple(s for s in styles if s in opt_dict) if opts: definition['opts'] = opts diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/comment.py --- a/kallithea/model/comment.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/comment.py Thu Feb 06 01:19:23 2020 +0100 @@ -31,7 +31,7 @@ from tg.i18n import ugettext as _ from kallithea.lib import helpers as h -from kallithea.lib.utils2 import extract_mentioned_users, safe_unicode +from kallithea.lib.utils2 import extract_mentioned_users from kallithea.model.db import ChangesetComment, PullRequest, Repository, User from kallithea.model.meta import Session from kallithea.model.notification import NotificationModel @@ -81,11 +81,10 @@ repo_name=repo.repo_name, revision=revision, anchor='comment-%s' % comment.comment_id) - subj = safe_unicode( - h.link_to('Re changeset: %(desc)s %(line)s' % + subj = h.link_to( + 'Re changeset: %(desc)s %(line)s' % {'desc': desc, 'line': line}, - comment_url) - ) + comment_url) # get the current participants of this changeset recipients = _list_changeset_commenters(revision) # add changeset author if it's known locally @@ -127,13 +126,12 @@ h.canonical_hostname())) comment_url = pull_request.url(canonical=True, anchor='comment-%s' % comment.comment_id) - subj = safe_unicode( - h.link_to('Re pull request %(pr_nice_id)s: %(desc)s %(line)s' % + subj = h.link_to( + 'Re pull request %(pr_nice_id)s: %(desc)s %(line)s' % {'desc': desc, 'pr_nice_id': comment.pull_request.nice_id(), 'line': line}, - comment_url) - ) + comment_url) # get the current participants of this pull request recipients = _list_pull_request_commenters(pull_request) recipients.append(pull_request.owner) @@ -257,7 +255,7 @@ paths = defaultdict(lambda: defaultdict(list)) for co in comments: paths[co.f_path][co.line_no].append(co) - return paths.items() + return sorted(paths.items()) def _get_comments(self, repo_id, revision=None, pull_request=None, inline=False, f_path=None, line_no=None): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/db.py --- a/kallithea/model/db.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/db.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,6 +25,7 @@ :license: GPLv3, see LICENSE.md for more details. """ +import base64 import collections import datetime import functools @@ -37,17 +38,18 @@ import ipaddr import sqlalchemy from beaker.cache import cache_region, region_invalidate -from sqlalchemy import * +from sqlalchemy import Boolean, Column, DateTime, Float, ForeignKey, Index, Integer, LargeBinary, String, Unicode, UnicodeText, UniqueConstraint from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import class_mapper, joinedload, relationship, validates from tg.i18n import lazy_ugettext as _ from webob.exc import HTTPNotFound import kallithea +from kallithea.lib import ext_json from kallithea.lib.caching_query import FromCache -from kallithea.lib.compat import json from kallithea.lib.exceptions import DefaultUserException -from kallithea.lib.utils2 import Optional, aslist, get_changeset_safe, get_clone_url, remove_prefix, safe_int, safe_str, safe_unicode, str2bool, urlreadable +from kallithea.lib.utils2 import ( + Optional, ascii_bytes, aslist, get_changeset_safe, get_clone_url, remove_prefix, safe_bytes, safe_int, safe_str, str2bool, urlreadable) from kallithea.lib.vcs import get_backend from kallithea.lib.vcs.backends.base import EmptyChangeset from kallithea.lib.vcs.utils.helpers import get_scm @@ -62,7 +64,8 @@ # BASE CLASSES #============================================================================== -_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest() +def _hash_key(k): + return hashlib.md5(safe_bytes(k)).hexdigest() class BaseDbModel(object): @@ -73,6 +76,7 @@ @classmethod def _get_keys(cls): """return column names for this model """ + # Note: not a normal dict - iterator gives "users.firstname", but keys gives "firstname" return class_mapper(cls).c.keys() def get_dict(self): @@ -90,7 +94,7 @@ # update with attributes from __json__ if callable(_json_attr): _json_attr = _json_attr() - for k, val in _json_attr.iteritems(): + for k, val in _json_attr.items(): d[k] = val return d @@ -135,8 +139,10 @@ return None if isinstance(value, cls): return value - if isinstance(value, (int, long)) or safe_str(value).isdigit(): + if isinstance(value, int): return cls.get(value) + if isinstance(value, str) and value.isdigit(): + return cls.get(int(value)) if callback is not None: return callback(value) @@ -163,12 +169,6 @@ Session().delete(obj) def __repr__(self): - if hasattr(self, '__unicode__'): - # python repr needs to return str - try: - return safe_str(self.__unicode__()) - except UnicodeDecodeError: - pass return '' % (self.__class__.__name__) @@ -185,9 +185,9 @@ ) SETTINGS_TYPES = { - 'str': safe_str, + 'str': safe_bytes, 'int': safe_int, - 'unicode': safe_unicode, + 'unicode': safe_str, 'bool': str2bool, 'list': functools.partial(aslist, sep=',') } @@ -205,7 +205,7 @@ @validates('_app_settings_value') def validate_settings_value(self, key, val): - assert type(val) == unicode + assert isinstance(val, str) return val @hybrid_property @@ -218,11 +218,9 @@ @app_settings_value.setter def app_settings_value(self, val): """ - Setter that will always make sure we use unicode in app_settings_value - - :param val: + Setter that will always make sure we use str in app_settings_value """ - self._app_settings_value = safe_unicode(val) + self._app_settings_value = safe_str(val) @hybrid_property def app_settings_type(self): @@ -232,13 +230,13 @@ def app_settings_type(self, val): if val not in self.SETTINGS_TYPES: raise Exception('type must be one of %s got %s' - % (self.SETTINGS_TYPES.keys(), val)) + % (list(self.SETTINGS_TYPES), val)) self._app_settings_type = val - def __unicode__(self): - return u"<%s('%s:%s[%s]')>" % ( + def __repr__(self): + return "<%s %s.%s=%r>" % ( self.__class__.__name__, - self.app_settings_name, self.app_settings_value, self.app_settings_type + self.app_settings_name, self.app_settings_type, self.app_settings_value ) @classmethod @@ -328,9 +326,9 @@ info = { 'modules': sorted(mods, key=lambda k: k[0].lower()), 'py_version': platform.python_version(), - 'platform': safe_unicode(platform.platform()), + 'platform': platform.platform(), 'kallithea_version': kallithea.__version__, - 'git_version': safe_unicode(check_git_version()), + 'git_version': str(check_git_version()), 'git_path': kallithea.CONFIG.get('git_path') } return info @@ -394,8 +392,9 @@ new_ui.ui_value = val def __repr__(self): - return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section, - self.ui_key, self.ui_value) + return '<%s %s.%s=%r>' % ( + self.__class__.__name__, + self.ui_section, self.ui_key, self.ui_value) class User(Base, BaseDbModel): @@ -520,20 +519,19 @@ return {} try: - return json.loads(self._user_data) + return ext_json.loads(self._user_data) except TypeError: return {} @user_data.setter def user_data(self, val): try: - self._user_data = json.dumps(val) + self._user_data = ascii_bytes(ext_json.dumps(val)) except Exception: log.error(traceback.format_exc()) - def __unicode__(self): - return u"<%s('id:%s:%s')>" % (self.__class__.__name__, - self.user_id, self.username) + def __repr__(self): + return "<%s %s: %r')>" % (self.__class__.__name__, self.user_id, self.username) @classmethod def guess_instance(cls, value): @@ -567,7 +565,7 @@ @classmethod def get_by_username(cls, username, case_insensitive=False, cache=False): if case_insensitive: - q = cls.query().filter(func.lower(cls.username) == func.lower(username)) + q = cls.query().filter(sqlalchemy.func.lower(cls.username) == sqlalchemy.func.lower(username)) else: q = cls.query().filter(cls.username == username) @@ -602,7 +600,7 @@ @classmethod def get_by_email(cls, email, cache=False): - q = cls.query().filter(func.lower(cls.email) == func.lower(email)) + q = cls.query().filter(sqlalchemy.func.lower(cls.email) == sqlalchemy.func.lower(email)) if cache: q = q.options(FromCache("sql_cache_short", @@ -612,7 +610,7 @@ if ret is None: q = UserEmailMap.query() # try fetching in alternate email map - q = q.filter(func.lower(UserEmailMap.email) == func.lower(email)) + q = q.filter(sqlalchemy.func.lower(UserEmailMap.email) == sqlalchemy.func.lower(email)) q = q.options(joinedload(UserEmailMap.user)) if cache: q = q.options(FromCache("sql_cache_short", @@ -772,9 +770,8 @@ ip_range=self._get_ip_range(self.ip_addr) ) - def __unicode__(self): - return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__, - self.user_id, self.ip_addr) + def __repr__(self): + return "<%s %s: %s>" % (self.__class__.__name__, self.user_id, self.ip_addr) class UserLog(Base, BaseDbModel): @@ -792,10 +789,10 @@ action = Column(UnicodeText(), nullable=False) action_date = Column(DateTime(timezone=False), nullable=False) - def __unicode__(self): - return u"<%s('id:%s:%s')>" % (self.__class__.__name__, - self.repository_name, - self.action) + def __repr__(self): + return "<%s %r: %r')>" % (self.__class__.__name__, + self.repository_name, + self.action) @property def action_as_day(self): @@ -834,21 +831,21 @@ return {} try: - return json.loads(self._group_data) + return ext_json.loads(self._group_data) except TypeError: return {} @group_data.setter def group_data(self, val): try: - self._group_data = json.dumps(val) + self._group_data = ascii_bytes(ext_json.dumps(val)) except Exception: log.error(traceback.format_exc()) - def __unicode__(self): - return u"<%s('id:%s:%s')>" % (self.__class__.__name__, - self.users_group_id, - self.users_group_name) + def __repr__(self): + return "<%s %s: %r')>" % (self.__class__.__name__, + self.users_group_id, + self.users_group_name) @classmethod def guess_instance(cls, value): @@ -858,7 +855,7 @@ def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): if case_insensitive: - q = cls.query().filter(func.lower(cls.users_group_name) == func.lower(group_name)) + q = cls.query().filter(sqlalchemy.func.lower(cls.users_group_name) == sqlalchemy.func.lower(group_name)) else: q = cls.query().filter(cls.users_group_name == group_name) if cache: @@ -1009,9 +1006,9 @@ primaryjoin='PullRequest.other_repo_id==Repository.repo_id', cascade="all, delete-orphan") - def __unicode__(self): - return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id, - safe_unicode(self.repo_name)) + def __repr__(self): + return "<%s %s: %r>" % (self.__class__.__name__, + self.repo_id, self.repo_name) @hybrid_property def landing_rev(self): @@ -1033,7 +1030,7 @@ @hybrid_property def changeset_cache(self): try: - cs_cache = json.loads(self._changeset_cache) # might raise on bad data + cs_cache = ext_json.loads(self._changeset_cache) # might raise on bad data cs_cache['raw_id'] # verify data, raise exception on error return cs_cache except (TypeError, KeyError, ValueError): @@ -1042,7 +1039,7 @@ @changeset_cache.setter def changeset_cache(self, val): try: - self._changeset_cache = json.dumps(val) + self._changeset_cache = ascii_bytes(ext_json.dumps(val)) except Exception: log.error(traceback.format_exc()) @@ -1055,7 +1052,7 @@ q = super(Repository, cls).query() if sorted: - q = q.order_by(func.lower(Repository.repo_name)) + q = q.order_by(sqlalchemy.func.lower(Repository.repo_name)) return q @@ -1083,7 +1080,7 @@ """Get the repo, defaulting to database case sensitivity. case_insensitive will be slower and should only be specified if necessary.""" if case_insensitive: - q = Session().query(cls).filter(func.lower(cls.repo_name) == func.lower(repo_name)) + q = Session().query(cls).filter(sqlalchemy.func.lower(cls.repo_name) == sqlalchemy.func.lower(repo_name)) else: q = Session().query(cls).filter(cls.repo_name == repo_name) q = q.options(joinedload(Repository.fork)) \ @@ -1163,7 +1160,7 @@ # names in the database, but that eventually needs to be converted # into a valid system path p += self.repo_name.split(Repository.url_sep()) - return os.path.join(*map(safe_unicode, p)) + return os.path.join(*p) @property def cache_keys(self): @@ -1190,7 +1187,7 @@ Creates an db based ui object for this repository """ from kallithea.lib.utils import make_ui - return make_ui(clear_session=False) + return make_ui() @classmethod def is_valid(cls, repo_name): @@ -1425,7 +1422,7 @@ return _c(rn) def scm_instance_no_cache(self): - repo_full_path = safe_str(self.repo_full_path) + repo_full_path = self.repo_full_path alias = get_scm(repo_full_path)[0] log.debug('Creating instance of %s repository from %s', alias, self.repo_full_path) @@ -1476,7 +1473,7 @@ q = super(RepoGroup, cls).query() if sorted: - q = q.order_by(func.lower(RepoGroup.group_name)) + q = q.order_by(sqlalchemy.func.lower(RepoGroup.group_name)) return q @@ -1484,9 +1481,9 @@ self.group_name = group_name self.parent_group = parent_group - def __unicode__(self): - return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id, - self.group_name) + def __repr__(self): + return "<%s %s: %s>" % (self.__class__.__name__, + self.group_id, self.group_name) @classmethod def _generate_choice(cls, repo_group): @@ -1515,7 +1512,7 @@ group_name = group_name.rstrip('/') if case_insensitive: gr = cls.query() \ - .filter(func.lower(cls.group_name) == func.lower(group_name)) + .filter(sqlalchemy.func.lower(cls.group_name) == sqlalchemy.func.lower(group_name)) else: gr = cls.query() \ .filter(cls.group_name == group_name) @@ -1731,8 +1728,8 @@ permission_id = Column(Integer(), primary_key=True) permission_name = Column(String(255), nullable=False) - def __unicode__(self): - return u"<%s('%s:%s')>" % ( + def __repr__(self): + return "<%s %s: %r>" % ( self.__class__.__name__, self.permission_id, self.permission_name ) @@ -1797,8 +1794,9 @@ Session().add(n) return n - def __unicode__(self): - return u'<%s => %s >' % (self.user, self.repository) + def __repr__(self): + return '<%s %s at %s: %s>' % ( + self.__class__.__name__, self.user, self.repository, self.permission) class UserUserGroupToPerm(Base, BaseDbModel): @@ -1826,8 +1824,9 @@ Session().add(n) return n - def __unicode__(self): - return u'<%s => %s >' % (self.user, self.user_group) + def __repr__(self): + return '<%s %s at %s: %s>' % ( + self.__class__.__name__, self.user, self.user_group, self.permission) class UserToPerm(Base, BaseDbModel): @@ -1844,8 +1843,9 @@ user = relationship('User') permission = relationship('Permission') - def __unicode__(self): - return u'<%s => %s >' % (self.user, self.permission) + def __repr__(self): + return '<%s %s: %s>' % ( + self.__class__.__name__, self.user, self.permission) class UserGroupRepoToPerm(Base, BaseDbModel): @@ -1873,8 +1873,9 @@ Session().add(n) return n - def __unicode__(self): - return u' %s >' % (self.users_group, self.repository) + def __repr__(self): + return '<%s %s at %s: %s>' % ( + self.__class__.__name__, self.users_group, self.repository, self.permission) class UserGroupUserGroupToPerm(Base, BaseDbModel): @@ -1902,8 +1903,9 @@ Session().add(n) return n - def __unicode__(self): - return u' %s >' % (self.target_user_group, self.user_group) + def __repr__(self): + return '<%s %s at %s: %s>' % ( + self.__class__.__name__, self.user_group, self.target_user_group, self.permission) class UserGroupToPerm(Base, BaseDbModel): @@ -2006,7 +2008,7 @@ user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') - follows_repository = relationship('Repository', order_by=lambda: func.lower(Repository.repo_name)) + follows_repository = relationship('Repository', order_by=lambda: sqlalchemy.func.lower(Repository.repo_name)) @classmethod def get_repo_followers(cls, repo_id): @@ -2035,8 +2037,8 @@ self.cache_args = repo_name self.cache_active = False - def __unicode__(self): - return u"<%s('%s:%s[%s]')>" % ( + def __repr__(self): + return "<%s %s: %s=%s" % ( self.__class__.__name__, self.cache_id, self.cache_key, self.cache_active) @@ -2087,11 +2089,11 @@ """ inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all() log.debug('for repo %s got %s invalidation objects', - safe_str(repo_name), inv_objs) + repo_name, inv_objs) for inv_obj in inv_objs: log.debug('marking %s key for invalidation based on repo_name=%s', - inv_obj, safe_str(repo_name)) + inv_obj, repo_name) Session().delete(inv_obj) Session().commit() @@ -2225,8 +2227,8 @@ comment = relationship('ChangesetComment') pull_request = relationship('PullRequest') - def __unicode__(self): - return u"<%s('%s:%s')>" % ( + def __repr__(self): + return "<%s %r by %r>" % ( self.__class__.__name__, self.status, self.author ) @@ -2278,7 +2280,7 @@ @revisions.setter def revisions(self, val): - self._revisions = safe_unicode(':'.join(val)) + self._revisions = ':'.join(val) @property def org_ref_parts(self): @@ -2446,7 +2448,9 @@ return (self.gist_expires != -1) & (time.time() > self.gist_expires) def __repr__(self): - return '' % (self.gist_type, self.gist_access_id) + return "<%s %s %s>" % ( + self.__class__.__name__, + self.gist_type, self.gist_access_id) @classmethod def guess_instance(cls, value): @@ -2511,14 +2515,12 @@ def scm_instance(self): from kallithea.lib.vcs import get_repo base_path = self.base_path() - return get_repo(os.path.join(*map(safe_str, - [base_path, self.gist_access_id]))) + return get_repo(os.path.join(base_path, self.gist_access_id)) class UserSshKeys(Base, BaseDbModel): __tablename__ = 'user_ssh_keys' __table_args__ = ( - Index('usk_public_key_idx', 'public_key'), Index('usk_fingerprint_idx', 'fingerprint'), UniqueConstraint('fingerprint'), _table_args_default_dict @@ -2544,5 +2546,5 @@ # the full public key is too long to be suitable as database key - instead, # use fingerprints similar to 'ssh-keygen -E sha256 -lf ~/.ssh/id_rsa.pub' self._public_key = full_key - enc_key = full_key.split(" ")[1] - self.fingerprint = hashlib.sha256(enc_key.decode('base64')).digest().encode('base64').replace('\n', '').rstrip('=') + enc_key = safe_bytes(full_key.split(" ")[1]) + self.fingerprint = base64.b64encode(hashlib.sha256(base64.b64decode(enc_key)).digest()).replace(b'\n', b'').rstrip(b'=').decode() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/forms.py --- a/kallithea/model/forms.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/forms.py Thu Feb 06 01:19:23 2020 +0100 @@ -238,7 +238,7 @@ return _PasswordResetConfirmationForm -def RepoForm(edit=False, old_data=None, supported_backends=BACKENDS.keys(), +def RepoForm(edit=False, old_data=None, supported_backends=BACKENDS, repo_groups=None, landing_revs=None): old_data = old_data or {} repo_groups = repo_groups or [] @@ -315,7 +315,7 @@ return _RepoFieldForm -def RepoForkForm(edit=False, old_data=None, supported_backends=BACKENDS.keys(), +def RepoForkForm(edit=False, old_data=None, supported_backends=BACKENDS, repo_groups=None, landing_revs=None): old_data = old_data or {} repo_groups = repo_groups or [] @@ -435,7 +435,7 @@ return _CustomDefaultPermissionsForm -def DefaultsForm(edit=False, old_data=None, supported_backends=BACKENDS.keys()): +def DefaultsForm(edit=False, old_data=None, supported_backends=BACKENDS): class _DefaultsForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = True diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/gist.py --- a/kallithea/model/gist.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/gist.py Thu Feb 06 01:19:23 2020 +0100 @@ -32,8 +32,8 @@ import time import traceback -from kallithea.lib.compat import json -from kallithea.lib.utils2 import AttributeDict, safe_int, safe_unicode, time_to_datetime +from kallithea.lib import ext_json +from kallithea.lib.utils2 import AttributeDict, ascii_bytes, safe_int, time_to_datetime from kallithea.model.db import Gist, Session, User from kallithea.model.repo import RepoModel from kallithea.model.scm import ScmModel @@ -45,12 +45,12 @@ GIST_METADATA_FILE = '.rc_gist_metadata' -def make_gist_id(): +def make_gist_access_id(): """Generate a random, URL safe, almost certainly unique gist identifier.""" rnd = random.SystemRandom() # use cryptographically secure system PRNG alphabet = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnpqrstuvwxyz' length = 20 - return u''.join(rnd.choice(alphabet) for _ in xrange(length)) + return u''.join(rnd.choice(alphabet) for _ in range(length)) class GistModel(object): @@ -82,7 +82,7 @@ 'gist_updated': time.time(), } with open(os.path.join(repo.path, '.hg', GIST_METADATA_FILE), 'wb') as f: - f.write(json.dumps(metadata)) + f.write(ascii_bytes(ext_json.dumps(metadata))) def get_gist(self, gist): return Gist.guess_instance(gist) @@ -108,7 +108,7 @@ :param lifetime: in minutes, -1 == forever """ owner = User.guess_instance(owner) - gist_id = make_gist_id() + gist_access_id = make_gist_access_id() lifetime = safe_int(lifetime, -1) gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1 log.debug('set GIST expiration date to: %s', @@ -117,21 +117,19 @@ # create the Database version gist = Gist() gist.gist_description = description - gist.gist_access_id = gist_id + gist.gist_access_id = gist_access_id gist.owner_id = owner.user_id gist.gist_expires = gist_expires - gist.gist_type = safe_unicode(gist_type) + gist.gist_type = gist_type Session().add(gist) Session().flush() # make database assign gist.gist_id if gist_type == Gist.GIST_PUBLIC: # use DB ID for easy to use GIST ID - gist_id = safe_unicode(gist.gist_id) - gist.gist_access_id = gist_id + gist.gist_access_id = str(gist.gist_id) - gist_repo_path = os.path.join(GIST_STORE_LOC, gist_id) - log.debug('Creating new %s GIST repo in %s', gist_type, gist_repo_path) + log.debug('Creating new %s GIST repo %s', gist_type, gist.gist_access_id) repo = RepoModel()._create_filesystem_repo( - repo_name=gist_id, repo_type='hg', repo_group=GIST_STORE_LOC) + repo_name=gist.gist_access_id, repo_type='hg', repo_group=GIST_STORE_LOC) processed_mapping = {} for filename in gist_mapping: @@ -155,7 +153,7 @@ # fake Kallithea Repository object fake_repo = AttributeDict(dict( - repo_name=gist_repo_path, + repo_name=os.path.join(GIST_STORE_LOC, gist.gist_access_id), scm_instance_no_cache=lambda: repo, )) ScmModel().create_nodes( @@ -219,7 +217,7 @@ # fake Kallithea Repository object fake_repo = AttributeDict(dict( - repo_name=gist_repo.path, + repo_name=os.path.join(GIST_STORE_LOC, gist.gist_access_id), scm_instance_no_cache=lambda: gist_repo, )) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/notification.py --- a/kallithea/model/notification.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/notification.py Thu Feb 06 01:19:23 2020 +0100 @@ -35,7 +35,6 @@ import kallithea from kallithea.lib import helpers as h -from kallithea.lib.utils2 import safe_unicode from kallithea.model.db import User @@ -178,14 +177,21 @@ try: subj = tmpl % kwargs except KeyError as e: - log.error('error generating email subject for %r from %s: %s', type_, ','.join(self._subj_map.keys()), e) + log.error('error generating email subject for %r from %s: %s', type_, ', '.join(self._subj_map), e) raise - l = [safe_unicode(x) for x in [kwargs.get('status_change'), kwargs.get('closing_pr') and _('Closing')] if x] - if l: + # gmail doesn't do proper threading but will ignore leading square + # bracket content ... so that is where we put status info + bracket_tags = [] + status_change = kwargs.get('status_change') + if status_change: + bracket_tags.append(str(status_change)) # apply str to evaluate LazyString before .join + if kwargs.get('closing_pr'): + bracket_tags.append(_('Closing')) + if bracket_tags: if subj.startswith('['): - subj = '[' + ', '.join(l) + ': ' + subj[1:] + subj = '[' + ', '.join(bracket_tags) + ': ' + subj[1:] else: - subj = '[' + ', '.join(l) + '] ' + subj + subj = '[' + ', '.join(bracket_tags) + '] ' + subj return subj def get_email_tmpl(self, type_, content_type, **kwargs): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/permission.py --- a/kallithea/model/permission.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/permission.py Thu Feb 06 01:19:23 2020 +0100 @@ -73,8 +73,7 @@ return '.'.join(perm_name.split('.')[:1]) perms = UserToPerm.query().filter(UserToPerm.user == user).all() - defined_perms_groups = map(_get_group, - (x.permission.permission_name for x in perms)) + defined_perms_groups = set(_get_group(x.permission.permission_name) for x in perms) log.debug('GOT ALREADY DEFINED:%s', perms) DEFAULT_PERMS = Permission.DEFAULT_USER_PERMISSIONS diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/pull_request.py --- a/kallithea/model/pull_request.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/pull_request.py Thu Feb 06 01:19:23 2020 +0100 @@ -33,7 +33,7 @@ from tg.i18n import ugettext as _ from kallithea.lib import helpers as h -from kallithea.lib.utils2 import extract_mentioned_users, safe_str, safe_unicode +from kallithea.lib.utils2 import ascii_bytes, extract_mentioned_users from kallithea.model.db import ChangesetStatus, PullRequest, PullRequestReviewer, User from kallithea.model.meta import Session from kallithea.model.notification import NotificationModel @@ -68,14 +68,12 @@ threading = ['%s-pr-%s@%s' % (pr.other_repo.repo_name, pr.pull_request_id, h.canonical_hostname())] - subject = safe_unicode( - h.link_to( - _('%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s') % + subject = h.link_to( + _('%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s') % {'user': user.username, 'pr_title': pr.title, 'pr_nice_id': pr.nice_id()}, - pr_url) - ) + pr_url) body = pr.description _org_ref_type, org_ref_name, _org_rev = pr.org_ref.split(':') _other_ref_type, other_ref_name, _other_rev = pr.other_ref.split(':') @@ -261,7 +259,7 @@ if self.org_repo.scm_instance.alias == 'git': # create a ref under refs/pull/ so that commits don't get garbage-collected - self.org_repo.scm_instance._repo["refs/pull/%d/head" % pr.pull_request_id] = safe_str(self.org_rev) + self.org_repo.scm_instance._repo[b"refs/pull/%d/head" % pr.pull_request_id] = ascii_bytes(self.org_rev) # reset state to under-review from kallithea.model.changeset_status import ChangesetStatusModel @@ -362,11 +360,11 @@ infos.append(_('No changes found on %s %s since previous iteration.') % (org_ref_type, org_ref_name)) # TODO: fail? - try: - title, old_v = re.match(r'(.*)\(v(\d+)\)\s*$', title).groups() - v = int(old_v) + 1 - except (AttributeError, ValueError): - v = 2 + v = 2 + m = re.match(r'(.*)\(v(\d+)\)\s*$', title) + if m is not None: + title = m.group(1) + v = int(m.group(2)) + 1 self.create_action.title = '%s (v%s)' % (title.strip(), v) # using a mail-like separator, insert new iteration info in description with latest first diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/repo.py --- a/kallithea/model/repo.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/repo.py Thu Feb 06 01:19:23 2020 +0100 @@ -39,7 +39,7 @@ from kallithea.lib.exceptions import AttachedForksError from kallithea.lib.hooks import log_delete_repository from kallithea.lib.utils import is_valid_repo_uri, make_ui -from kallithea.lib.utils2 import LazyProperty, get_current_authuser, obfuscate_url_pw, remove_prefix, safe_str, safe_unicode +from kallithea.lib.utils2 import LazyProperty, get_current_authuser, obfuscate_url_pw, remove_prefix from kallithea.lib.vcs.backends import get_backend from kallithea.model.db import ( Permission, RepoGroup, Repository, RepositoryField, Session, Statistics, Ui, User, UserGroup, UserGroupRepoGroupToPerm, UserGroupRepoToPerm, UserRepoGroupToPerm, UserRepoToPerm) @@ -119,7 +119,6 @@ @classmethod def _render_datatable(cls, tmpl, *args, **kwargs): - import kallithea from tg import tmpl_context as c, request, app_globals from tg.i18n import ugettext as _ @@ -128,7 +127,7 @@ tmpl = template.get_def(tmpl) kwargs.update(dict(_=_, h=h, c=c, request=request)) - return tmpl.render(*args, **kwargs) + return tmpl.render_unicode(*args, **kwargs) def get_repos_as_dict(self, repos_list, repo_groups_list=None, admin=False, @@ -290,7 +289,7 @@ # clone_uri is modified - if given a value, check it is valid if clone_uri != '': # will raise exception on error - is_valid_repo_uri(cur_repo.repo_type, clone_uri, make_ui(clear_session=False)) + is_valid_repo_uri(cur_repo.repo_type, clone_uri, make_ui()) cur_repo.clone_uri = clone_uri if 'repo_name' in kwargs: @@ -306,8 +305,7 @@ repo=cur_repo, user='default', perm=EMPTY_PERM ) # handle extra fields - for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), - kwargs): + for field in [k for k in kwargs if k.startswith(RepositoryField.PREFIX)]: k = RepositoryField.un_prefix_key(field) ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo) if ex_field: @@ -339,8 +337,8 @@ fork_of = Repository.guess_instance(fork_of) repo_group = RepoGroup.guess_instance(repo_group) try: - repo_name = safe_unicode(repo_name) - description = safe_unicode(description) + repo_name = repo_name + description = description # repo name is just a name of repository # while repo_name_full is a full qualified name that is combined # with name and path of group @@ -360,7 +358,7 @@ new_repo.private = private if clone_uri: # will raise exception on error - is_valid_repo_uri(repo_type, clone_uri, make_ui(clear_session=False)) + is_valid_repo_uri(repo_type, clone_uri, make_ui()) new_repo.clone_uri = clone_uri new_repo.landing_rev = landing_rev @@ -643,8 +641,7 @@ _paths = [repo_store_location] else: _paths = [self.repos_path, new_parent_path, repo_name] - # we need to make it str for mercurial - repo_path = os.path.join(*map(lambda x: safe_str(x), _paths)) + repo_path = os.path.join(*_paths) # check if this path is not a repository if is_valid_repo(repo_path, self.repos_path): @@ -655,13 +652,13 @@ raise Exception('This path %s is a valid group' % repo_path) log.info('creating repo %s in %s from url: `%s`', - repo_name, safe_unicode(repo_path), + repo_name, repo_path, obfuscate_url_pw(clone_uri)) backend = get_backend(repo_type) if repo_type == 'hg': - baseui = make_ui(clear_session=False) + baseui = make_ui() # patch and reset hooks section of UI config to not run any # hooks on creating remote repo for k, v in baseui.configitems('hooks'): @@ -676,7 +673,7 @@ raise Exception('Not supported repo_type %s expected hg/git' % repo_type) log.debug('Created repo %s with %s backend', - safe_unicode(repo_name), safe_unicode(repo_type)) + repo_name, repo_type) return repo def _rename_filesystem_repo(self, old, new): @@ -688,8 +685,8 @@ """ log.info('renaming repo from %s to %s', old, new) - old_path = safe_str(os.path.join(self.repos_path, old)) - new_path = safe_str(os.path.join(self.repos_path, new)) + old_path = os.path.join(self.repos_path, old) + new_path = os.path.join(self.repos_path, new) if os.path.isdir(new_path): raise Exception( 'Was trying to rename to already existing dir %s' % new_path @@ -704,7 +701,7 @@ :param repo: repo object """ - rm_path = safe_str(os.path.join(self.repos_path, repo.repo_name)) + rm_path = os.path.join(self.repos_path, repo.repo_name) log.info("Removing %s", rm_path) _now = datetime.now() @@ -715,6 +712,6 @@ args = repo.group.full_path_splitted + [_d] _d = os.path.join(*args) if os.path.exists(rm_path): - shutil.move(rm_path, safe_str(os.path.join(self.repos_path, _d))) + shutil.move(rm_path, os.path.join(self.repos_path, _d)) else: log.error("Can't find repo to delete in %r", rm_path) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/scm.py --- a/kallithea/model/scm.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/scm.py Thu Feb 06 01:19:23 2020 +0100 @@ -25,7 +25,6 @@ :license: GPLv3, see LICENSE.md for more details. """ -import cStringIO import logging import os import posixpath @@ -42,7 +41,7 @@ from kallithea.lib.exceptions import IMCCommitError, NonRelativePathError from kallithea.lib.hooks import process_pushed_raw_ids from kallithea.lib.utils import action_logger, get_filesystem_repos, make_ui -from kallithea.lib.utils2 import safe_str, safe_unicode, set_hook_environment +from kallithea.lib.utils2 import safe_bytes, set_hook_environment from kallithea.lib.vcs import get_backend from kallithea.lib.vcs.backends.base import EmptyChangeset from kallithea.lib.vcs.exceptions import RepositoryError @@ -140,9 +139,11 @@ cls = Repository if isinstance(instance, cls): return instance - elif isinstance(instance, int) or safe_str(instance).isdigit(): + elif isinstance(instance, int): return cls.get(instance) - elif isinstance(instance, basestring): + elif isinstance(instance, str): + if instance.isdigit(): + return cls.get(int(instance)) return cls.get_by_repo_name(instance) elif instance is not None: raise Exception('given object must be int, basestr or Instance' @@ -161,7 +162,8 @@ def repo_scan(self, repos_path=None): """ Listing of repositories in given path. This path should not be a - repository itself. Return a dictionary of repository objects + repository itself. Return a dictionary of repository objects mapping to + vcs instances. :param repos_path: path to directory containing repositories """ @@ -187,10 +189,10 @@ klass = get_backend(path[0]) - if path[0] == 'hg' and path[0] in BACKENDS.keys(): - repos[name] = klass(safe_str(path[1]), baseui=baseui) + if path[0] == 'hg' and path[0] in BACKENDS: + repos[name] = klass(path[1], baseui=baseui) - if path[0] == 'git' and path[0] in BACKENDS.keys(): + if path[0] == 'git' and path[0] in BACKENDS: repos[name] = klass(path[1]) except OSError: continue @@ -394,17 +396,8 @@ """ user = User.guess_instance(user) IMC = self._get_IMC_module(repo.alias) - - # decoding here will force that we have proper encoded values - # in any other case this will throw exceptions and deny commit - content = safe_str(content) - path = safe_str(f_path) - # message and author needs to be unicode - # proper backend should then translate that into required type - message = safe_unicode(message) - author = safe_unicode(author) imc = IMC(repo) - imc.change(FileNode(path, content, mode=cs.get_file_mode(f_path))) + imc.change(FileNode(f_path, content, mode=cs.get_file_mode(f_path))) try: tip = imc.commit(message=message, author=author, parents=[cs], branch=cs.branch) @@ -480,22 +473,14 @@ for f_path in nodes: content = nodes[f_path]['content'] f_path = self._sanitize_path(f_path) - f_path = safe_str(f_path) - # decoding here will force that we have proper encoded values - # in any other case this will throw exceptions and deny commit - if isinstance(content, (basestring,)): - content = safe_str(content) - elif isinstance(content, (file, cStringIO.OutputType,)): + if not isinstance(content, str) and not isinstance(content, bytes): content = content.read() - else: - raise Exception('Content is of unrecognized type %s' % ( - type(content) - )) processed_nodes.append((f_path, content)) - message = safe_unicode(message) + message = message committer = user.full_contact - author = safe_unicode(author) if author else committer + if not author: + author = committer IMC = self._get_IMC_module(scm_instance.alias) imc = IMC(scm_instance) @@ -536,9 +521,10 @@ user = User.guess_instance(user) scm_instance = repo.scm_instance_no_cache() - message = safe_unicode(message) + message = message committer = user.full_contact - author = safe_unicode(author) if author else committer + if not author: + author = committer imc_class = self._get_IMC_module(scm_instance.alias) imc = imc_class(scm_instance) @@ -616,9 +602,10 @@ content = nodes[f_path].get('content') processed_nodes.append((f_path, content)) - message = safe_unicode(message) + message = message committer = user.full_contact - author = safe_unicode(author) if author else committer + if not author: + author = committer IMC = self._get_IMC_module(scm_instance.alias) imc = IMC(scm_instance) @@ -673,18 +660,18 @@ repo = repo.scm_instance branches_group = ([(u'branch:%s' % k, k) for k, v in - repo.branches.iteritems()], _("Branches")) + repo.branches.items()], _("Branches")) hist_l.append(branches_group) choices.extend([x[0] for x in branches_group[0]]) if repo.alias == 'hg': bookmarks_group = ([(u'book:%s' % k, k) for k, v in - repo.bookmarks.iteritems()], _("Bookmarks")) + repo.bookmarks.items()], _("Bookmarks")) hist_l.append(bookmarks_group) choices.extend([x[0] for x in bookmarks_group[0]]) tags_group = ([(u'tag:%s' % k, k) for k, v in - repo.tags.iteritems()], _("Tags")) + repo.tags.items()], _("Tags")) hist_l.append(tags_group) choices.extend([x[0] for x in tags_group[0]]) @@ -702,7 +689,7 @@ # FIXME This may not work on Windows and may need a shell wrapper script. return (kallithea.CONFIG.get('git_hook_interpreter') or sys.executable - or '/usr/bin/env python2') + or '/usr/bin/env python3') def install_git_hooks(self, repo, force_create=False): """ @@ -718,11 +705,11 @@ if not os.path.isdir(loc): os.makedirs(loc) - tmpl_post = "#!%s\n" % self._get_git_hook_interpreter() + tmpl_post = b"#!%s\n" % safe_bytes(self._get_git_hook_interpreter()) tmpl_post += pkg_resources.resource_string( 'kallithea', os.path.join('config', 'post_receive_tmpl.py') ) - tmpl_pre = "#!%s\n" % self._get_git_hook_interpreter() + tmpl_pre = b"#!%s\n" % safe_bytes(self._get_git_hook_interpreter()) tmpl_pre += pkg_resources.resource_string( 'kallithea', os.path.join('config', 'pre_receive_tmpl.py') ) @@ -736,12 +723,11 @@ log.debug('hook exists, checking if it is from kallithea') with open(_hook_file, 'rb') as f: data = f.read() - matches = re.compile(r'(?:%s)\s*=\s*(.*)' - % 'KALLITHEA_HOOK_VER').search(data) + matches = re.search(br'^KALLITHEA_HOOK_VER\s*=\s*(.*)$', data, flags=re.MULTILINE) if matches: try: ver = matches.groups()[0] - log.debug('got %s it is kallithea', ver) + log.debug('Found Kallithea hook - it has KALLITHEA_HOOK_VER %r', ver) has_hook = True except Exception: log.error(traceback.format_exc()) @@ -753,9 +739,9 @@ log.debug('writing %s hook file !', h_type) try: with open(_hook_file, 'wb') as f: - tmpl = tmpl.replace('_TMPL_', kallithea.__version__) + tmpl = tmpl.replace(b'_TMPL_', safe_bytes(kallithea.__version__)) f.write(tmpl) - os.chmod(_hook_file, 0755) + os.chmod(_hook_file, 0o755) except IOError as e: log.error('error writing %s: %s', _hook_file, e) else: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/ssh_key.py --- a/kallithea/model/ssh_key.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/ssh_key.py Thu Feb 06 01:19:23 2020 +0100 @@ -29,7 +29,8 @@ from tg.i18n import ugettext as _ from kallithea.lib import ssh -from kallithea.lib.utils2 import safe_str, str2bool +from kallithea.lib.utils2 import str2bool +from kallithea.lib.vcs.exceptions import RepositoryError from kallithea.model.db import User, UserSshKeys from kallithea.model.meta import Session @@ -37,7 +38,7 @@ log = logging.getLogger(__name__) -class SshKeyModelException(Exception): +class SshKeyModelException(RepositoryError): """Exception raised by SshKeyModel methods to report errors""" @@ -53,7 +54,7 @@ try: keytype, pub, comment = ssh.parse_pub_key(public_key) except ssh.SshKeyParseError as e: - raise SshKeyModelException(_('SSH key %r is invalid: %s') % (safe_str(public_key), e.message)) + raise SshKeyModelException(_('SSH key %r is invalid: %s') % (public_key, e.args[0])) if not description.strip(): description = comment.strip() @@ -72,21 +73,19 @@ return new_ssh_key - def delete(self, public_key, user=None): + def delete(self, fingerprint, user): """ - Deletes given public_key, if user is set it also filters the object for - deletion by given user. + Deletes ssh key with given fingerprint for the given user. Will raise SshKeyModelException on errors """ - ssh_key = UserSshKeys.query().filter(UserSshKeys._public_key == public_key) + ssh_key = UserSshKeys.query().filter(UserSshKeys.fingerprint == fingerprint) - if user: - user = User.guess_instance(user) - ssh_key = ssh_key.filter(UserSshKeys.user_id == user.user_id) + user = User.guess_instance(user) + ssh_key = ssh_key.filter(UserSshKeys.user_id == user.user_id) ssh_key = ssh_key.scalar() if ssh_key is None: - raise SshKeyModelException(_('SSH key %r not found') % safe_str(public_key)) + raise SshKeyModelException(_('SSH key with fingerprint %r found') % fingerprint) Session().delete(ssh_key) def get_ssh_keys(self, user): @@ -116,7 +115,7 @@ # Now, test that the directory is or was created in a readable way by previous. if not (os.path.isdir(authorized_keys_dir) and os.access(authorized_keys_dir, os.W_OK)): - raise Exception("Directory of authorized_keys cannot be written to so authorized_keys file %s cannot be written" % (authorized_keys)) + raise SshKeyModelException("Directory of authorized_keys cannot be written to so authorized_keys file %s cannot be written" % (authorized_keys)) # Make sure we don't overwrite a key file with important content if os.path.exists(authorized_keys): @@ -127,10 +126,11 @@ elif ssh.SSH_OPTIONS in l and ' ssh-serve ' in l: pass # Kallithea entries are ok to overwrite else: - raise Exception("Safety check failed, found %r in %s - please review and remove it" % (l.strip(), authorized_keys)) + raise SshKeyModelException("Safety check failed, found %r line in %s - please remove it if Kallithea should manage the file" % (l.strip(), authorized_keys)) fh, tmp_authorized_keys = tempfile.mkstemp('.authorized_keys', dir=os.path.dirname(authorized_keys)) with os.fdopen(fh, 'w') as f: + f.write("# WARNING: This .ssh/authorized_keys file is managed by Kallithea. Manual editing or adding new entries will make Kallithea back off.\n") for key in UserSshKeys.query().join(UserSshKeys.user).filter(User.active == True): f.write(ssh.authorized_keys_line(kallithea_cli_path, config['__file__'], key)) os.chmod(tmp_authorized_keys, stat.S_IRUSR | stat.S_IWUSR) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/user.py --- a/kallithea/model/user.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/user.py Thu Feb 06 01:19:23 2020 +0100 @@ -38,7 +38,7 @@ from kallithea.lib.caching_query import FromCache from kallithea.lib.exceptions import DefaultUserException, UserOwnsReposException -from kallithea.lib.utils2 import generate_api_key, get_current_authuser, safe_unicode +from kallithea.lib.utils2 import generate_api_key, get_current_authuser from kallithea.model.db import Permission, User, UserEmailMap, UserIpMap, UserToPerm from kallithea.model.meta import Session @@ -142,10 +142,8 @@ 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 = extern_name + new_user.extern_type = extern_type new_user.name = firstname new_user.lastname = lastname diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/user_group.py --- a/kallithea/model/user_group.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/user_group.py Thu Feb 06 01:19:23 2020 +0100 @@ -126,7 +126,7 @@ if k == 'users_group_members': members_list = [] if v: - v = [v] if isinstance(v, basestring) else v + v = [v] if isinstance(v, str) else v for u_id in set(v): member = UserGroupMember(user_group.users_group_id, u_id) members_list.append(member) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/model/validators.py --- a/kallithea/model/validators.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/model/validators.py Thu Feb 06 01:19:23 2020 +0100 @@ -235,7 +235,7 @@ def _validate_python(self, value, state): try: - (value or '').decode('ascii') + (value or '').encode('ascii') except UnicodeError: msg = self.message('invalid_password', state) raise formencode.Invalid(msg, value, state,) @@ -412,7 +412,7 @@ if url and url != value.get('clone_uri_hidden'): try: - is_valid_repo_uri(repo_type, url, make_ui(clear_session=False)) + is_valid_repo_uri(repo_type, url, make_ui()) except Exception: log.exception('URL validation failed') msg = self.message('clone_uri', state) @@ -544,7 +544,7 @@ # CLEAN OUT ORG VALUE FROM NEW MEMBERS, and group them using new_perms_group = defaultdict(dict) - for k, v in value.copy().iteritems(): + for k, v in value.copy().items(): if k.startswith('perm_new_member'): del value[k] _type, part = k.split('perm_new_member_') @@ -556,15 +556,15 @@ new_perms_group[pos][_key] = v # fill new permissions in order of how they were added - for k in sorted(map(int, new_perms_group.keys())): - perm_dict = new_perms_group[str(k)] + for k in sorted(new_perms_group, key=lambda k: int(k)): + perm_dict = new_perms_group[k] new_member = perm_dict.get('name') new_perm = perm_dict.get('perm') new_type = perm_dict.get('type') if new_member and new_perm and new_type: perms_new.add((new_member, new_perm, new_type)) - for k, v in value.iteritems(): + for k, v in value.items(): if k.startswith('u_perm_') or k.startswith('g_perm_'): member = k[7:] t = {'u': 'user', @@ -782,7 +782,7 @@ def _convert_to_python(self, value, state): # filter empty values - return filter(lambda s: s not in [None, ''], value) + return [s for s in value if s not in [None, '']] def _validate_python(self, value, state): from kallithea.lib import auth_modules diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/public/js/base.js --- a/kallithea/public/js/base.js Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/public/js/base.js Thu Feb 06 01:19:23 2020 +0100 @@ -697,7 +697,7 @@ if (!confirm('Confirm to delete this pull request')) { return false; } - var comments = $('.comment').size(); + var comments = $('.comment').length; if (comments > 0 && !confirm('Confirm again to delete this pull request with {0} comments'.format(comments))) { return false; diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/about.html --- a/kallithea/templates/about.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/about.html Thu Feb 06 01:19:23 2020 +0100 @@ -24,16 +24,27 @@ necessarily limited to the following:

      -
    • Copyright © 2012–2019, Mads Kiilerich
    • +
    • Copyright © 2012–2020, Mads Kiilerich
    • +
    • Copyright © 2014–2020, Thomas De Schampheleire
    • +
    • Copyright © 2020, Dennis Fink
    • Copyright © 2012, 2014–2017, 2019, Andrej Shadura
    • -
    • Copyright © 2014–2019, Thomas De Schampheleire
    • Copyright © 2015–2017, 2019, Étienne Gilli
    • Copyright © 2017–2019, Allan Nordhøy
    • Copyright © 2018–2019, ssantos
    • +
    • Copyright © 2019, Adi Kriegisch
    • Copyright © 2019, Danni Randeris
    • Copyright © 2019, Edmund Wong
    • +
    • Copyright © 2019, Elizabeth Sherrock
    • +
    • Copyright © 2019, Hüseyin Tunç
    • +
    • Copyright © 2019, leela
    • Copyright © 2019, Manuel Jacob
    • +
    • Copyright © 2019, Mateusz Mendel
    • +
    • Copyright © 2019, Nathan
    • +
    • Copyright © 2019, Oleksandr Shtalinberg
    • +
    • Copyright © 2019, Private
    • +
    • Copyright © 2019, THANOS SIOURDAKIS
    • Copyright © 2019, Wolfgang Scherer
    • +
    • Copyright © 2019, Христо Станев
    • Copyright © 2012, 2014–2018, Dominik Ruf
    • Copyright © 2014–2015, 2018, Michal Čihař
    • Copyright © 2015, 2018, Branko Majic
    • diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/admin/gists/edit.html --- a/kallithea/templates/admin/gists/edit.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/admin/gists/edit.html Thu Feb 06 01:19:23 2020 +0100 @@ -67,13 +67,13 @@ % for cnt, file in enumerate(c.files):
      - - + +
      - +
      diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/admin/gists/index.html --- a/kallithea/templates/admin/gists/index.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/admin/gists/index.html Thu Feb 06 01:19:23 2020 +0100 @@ -61,7 +61,7 @@
      ${gist.gist_description}
    % endfor - ${c.gists_pager.pager(**request.GET.mixed())} + ${c.gists_pager.pager()} %else:
    ${_('There are no gists yet')}
    %endif diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/admin/gists/show.html --- a/kallithea/templates/admin/gists/show.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/admin/gists/show.html Thu Feb 06 01:19:23 2020 +0100 @@ -76,10 +76,10 @@
    - ${h.safe_unicode(file.path)} + ${file.path}
    - ${h.link_to(_('Show as raw'),h.url('formatted_gist_file', gist_id=c.gist.gist_access_id, format='raw', revision=file.changeset.raw_id, f_path=h.safe_unicode(file.path)),class_="btn btn-default btn-xs")} + ${h.link_to(_('Show as raw'),h.url('formatted_gist_file', gist_id=c.gist.gist_access_id, format='raw', revision=file.changeset.raw_id, f_path=file.path),class_="btn btn-default btn-xs")}
    diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/admin/my_account/my_account_ssh_keys.html --- a/kallithea/templates/admin/my_account/my_account_ssh_keys.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/admin/my_account/my_account_ssh_keys.html Thu Feb 06 01:19:23 2020 +0100 @@ -23,7 +23,7 @@ ${h.form(url('my_account_ssh_keys_delete'))} - ${h.hidden('del_public_key', ssh_key.public_key)} + ${h.hidden('del_public_key_fingerprint', ssh_key.fingerprint)}
    + %else: + ${h.hidden('clone_ssh_tmpl', size=80, class_='form-control')} %endif
    diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/admin/users/user_edit_ssh_keys.html --- a/kallithea/templates/admin/users/user_edit_ssh_keys.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/admin/users/user_edit_ssh_keys.html Thu Feb 06 01:19:23 2020 +0100 @@ -23,7 +23,7 @@ ${h.form(url('edit_user_ssh_keys_delete', id=c.user.user_id))} - ${h.hidden('del_public_key', ssh_key.public_key)} + ${h.hidden('del_public_key_fingerprint', ssh_key.fingerprint)} - ${message} + ${message.message|n}
    % endfor % endif diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/base/perms_summary.html --- a/kallithea/templates/base/perms_summary.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/base/perms_summary.html Thu Feb 06 01:19:23 2020 +0100 @@ -5,7 +5,7 @@ <%def name="perms_summary(permissions, show_all=False, actions=True)">
    - %for section in sorted(permissions.keys()): + %for section in sorted(permissions):

    ${section.replace("_"," ").capitalize()}

    %if section != 'global': diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/changeset/changeset.html --- a/kallithea/templates/changeset/changeset.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/changeset/changeset.html Thu Feb 06 01:19:23 2020 +0100 @@ -90,16 +90,14 @@ ${h.person(c.changeset.author,'full_name_and_username')} - ${h.age(c.changeset.date,True)} ${h.fmt_date(c.changeset.date)}
    ${h.email_or_none(c.changeset.author)}
    - <% rev = c.changeset.extra.get('source') %> - %if rev: + %if c.changeset_graft_source_hash:
    - ${_('Grafted from:')} ${h.link_to(h.short_id(rev),h.url('changeset_home',repo_name=c.repo_name,revision=rev), class_="changeset_hash")} + ${_('Grafted from:')} ${h.link_to(h.short_id(c.changeset_graft_source_hash),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset_graft_source_hash), class_="changeset_hash")}
    %endif - <% rev = c.changeset.extra.get('transplant_source', '').encode('hex') %> - %if rev: + %if c.changeset_transplant_source_hash:
    - ${_('Transplanted from:')} ${h.link_to(h.short_id(rev),h.url('changeset_home',repo_name=c.repo_name,revision=rev), class_="changeset_hash")} + ${_('Transplanted from:')} ${h.link_to(h.short_id(c.changeset_transplant_source_hash),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset_transplant_source_hash), class_="changeset_hash")}
    %endif @@ -145,7 +143,7 @@ %for fid, url_fid, op, a_path, path, diff, stats in file_diff_data:
    - ${h.link_to(h.safe_unicode(path), '#%s' % fid)} + ${h.link_to(path, '#%s' % fid)}
    ${h.fancy_file_stats(stats)}
    diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/changeset/changeset_file_comment.html --- a/kallithea/templates/changeset/changeset_file_comment.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/changeset/changeset_file_comment.html Thu Feb 06 01:19:23 2020 +0100 @@ -163,8 +163,8 @@ ## original location of comments ... but the ones outside diff context remains here
    %for f_path, lines in c.inline_comments: - %for line_no, comments in lines.iteritems(): -
    + %for line_no, comments in lines.items(): +
    %for co in comments: ${comment_block(co)} %endfor @@ -198,7 +198,7 @@ $(window).on('beforeunload', function(){ var $textareas = $('.comment-inline-form textarea[name=text]'); - if($textareas.size() > 1 || + if($textareas.length > 1 || $textareas.val()) { // this message will not be displayed on all browsers // (e.g. some versions of Firefox), but the user will still be warned diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/changeset/changeset_range.html --- a/kallithea/templates/changeset/changeset_range.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/changeset/changeset_range.html Thu Feb 06 01:19:23 2020 +0100 @@ -56,7 +56,7 @@
    - ${h.link_to(h.safe_unicode(path), '#%s' % fid)} + ${h.link_to(path, '#%s' % fid)}
    ${h.fancy_file_stats(stats)}
    diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/changeset/diff_block.html --- a/kallithea/templates/changeset/diff_block.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/changeset/diff_block.html Thu Feb 06 01:19:23 2020 +0100 @@ -22,7 +22,7 @@
    - ${h.safe_unicode(cs_filename)} + ${cs_filename}
    @@ -57,13 +57,13 @@ %endif - + - + - + - + ${c.ignorews_url(request.GET, url_fid)} ${c.context_url(request.GET, url_fid)} @@ -73,7 +73,7 @@ ${h.checkbox('checkbox-show-inline-' + id_fid, checked="checked",class_="show-inline-comments",**{'data-id_for':id_fid})}
    -
    +
    ${diff|n} %if op and cs_filename.rsplit('.')[-1] in ['png', 'gif', 'jpg', 'bmp']:
    Show images
    diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/compare/compare_diff.html --- a/kallithea/templates/compare/compare_diff.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/compare/compare_diff.html Thu Feb 06 01:19:23 2020 +0100 @@ -72,7 +72,7 @@
    - ${h.link_to(h.safe_unicode(path), '#%s' % fid)} + ${h.link_to(path, '#%s' % fid)}
    ${h.fancy_file_stats(stats)}
    diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/templates/files/diff_2way.html --- a/kallithea/templates/files/diff_2way.html Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/templates/files/diff_2way.html Thu Feb 06 01:19:23 2020 +0100 @@ -34,22 +34,22 @@
    - ${h.link_to(h.safe_unicode(c.node1.path),h.url('files_home',repo_name=c.repo_name, - revision=c.cs2.raw_id,f_path=h.safe_unicode(c.node1.path)))} + ${h.link_to(c.node1.path,h.url('files_home',repo_name=c.repo_name, + revision=c.cs2.raw_id,f_path=c.node1.path))}
    - - - - ${h.checkbox('ignorews', label=_('Ignore whitespace'))} @@ -61,13 +61,17 @@
    ',), ('mailto:test@example.com',), ('file:///etc/passwd',), @@ -126,16 +128,16 @@ ('non-absolute-path',), ]) def test_login_bad_came_froms(self, url_came_from): - response = self.app.post(url(controller='login', action='index', + response = self.app.post(base.url(controller='login', action='index', came_from=url_came_from), - {'username': TEST_USER_ADMIN_LOGIN, - 'password': TEST_USER_ADMIN_PASS, + {'username': base.TEST_USER_ADMIN_LOGIN, + 'password': base.TEST_USER_ADMIN_PASS, '_session_csrf_secret_token': self.session_csrf_secret_token()}, status=400) def test_login_short_password(self): - response = self.app.post(url(controller='login', action='index'), - {'username': TEST_USER_ADMIN_LOGIN, + response = self.app.post(base.url(controller='login', action='index'), + {'username': base.TEST_USER_ADMIN_LOGIN, 'password': 'as', '_session_csrf_secret_token': self.session_csrf_secret_token()}) assert response.status == '200 OK' @@ -143,7 +145,7 @@ response.mustcontain('Enter 3 characters or more') def test_login_wrong_username_password(self): - response = self.app.post(url(controller='login', action='index'), + response = self.app.post(base.url(controller='login', action='index'), {'username': 'error', 'password': 'test12', '_session_csrf_secret_token': self.session_csrf_secret_token()}) @@ -151,8 +153,8 @@ response.mustcontain('Invalid username or password') def test_login_non_ascii(self): - response = self.app.post(url(controller='login', action='index'), - {'username': TEST_USER_REGULAR_LOGIN, + response = self.app.post(base.url(controller='login', action='index'), + {'username': base.TEST_USER_REGULAR_LOGIN, 'password': 'blåbærgrød', '_session_csrf_secret_token': self.session_csrf_secret_token()}) @@ -160,63 +162,61 @@ # verify that get arguments are correctly passed along login redirection - @parametrize('args,args_encoded', [ - ({'foo':'one', 'bar':'two'}, (('foo', 'one'), ('bar', 'two'))), - ({'blue': u'blå'.encode('utf-8'), 'green':u'grøn'}, - (('blue', u'blå'.encode('utf-8')), ('green', u'grøn'.encode('utf-8')))), + @base.parametrize('args', [ + {'foo':'one', 'bar':'two'}, + {'blue': u'blå', 'green': u'grøn'}, ]) - def test_redirection_to_login_form_preserves_get_args(self, args, args_encoded): + def test_redirection_to_login_form_preserves_get_args(self, args): with fixture.anon_access(False): - response = self.app.get(url(controller='summary', action='index', - repo_name=HG_REPO, + response = self.app.get(base.url(controller='summary', action='index', + repo_name=base.HG_REPO, **args)) assert response.status == '302 Found' - came_from = urlparse.parse_qs(urlparse.urlparse(response.location).query)['came_from'][0] - came_from_qs = urlparse.parse_qsl(urlparse.urlparse(came_from).query) - for encoded in args_encoded: - assert encoded in came_from_qs + came_from = urllib.parse.parse_qs(urllib.parse.urlparse(response.location).query)['came_from'][0] + came_from_qs = urllib.parse.parse_qsl(urllib.parse.urlparse(came_from).query) + assert sorted(came_from_qs) == sorted(args.items()) - @parametrize('args,args_encoded', [ + @base.parametrize('args,args_encoded', [ ({'foo':'one', 'bar':'two'}, ('foo=one', 'bar=two')), ({'blue': u'blå', 'green':u'grøn'}, ('blue=bl%C3%A5', 'green=gr%C3%B8n')), ]) def test_login_form_preserves_get_args(self, args, args_encoded): - response = self.app.get(url(controller='login', action='index', - came_from=url('/_admin/users', **args))) - came_from = urlparse.parse_qs(urlparse.urlparse(response.form.action).query)['came_from'][0] + response = self.app.get(base.url(controller='login', action='index', + came_from=base.url('/_admin/users', **args))) + came_from = urllib.parse.parse_qs(urllib.parse.urlparse(response.form.action).query)['came_from'][0] for encoded in args_encoded: assert encoded in came_from - @parametrize('args,args_encoded', [ + @base.parametrize('args,args_encoded', [ ({'foo':'one', 'bar':'two'}, ('foo=one', 'bar=two')), ({'blue': u'blå', 'green':u'grøn'}, ('blue=bl%C3%A5', 'green=gr%C3%B8n')), ]) def test_redirection_after_successful_login_preserves_get_args(self, args, args_encoded): - response = self.app.post(url(controller='login', action='index', - came_from=url('/_admin/users', **args)), - {'username': TEST_USER_ADMIN_LOGIN, - 'password': TEST_USER_ADMIN_PASS, + response = self.app.post(base.url(controller='login', action='index', + came_from=base.url('/_admin/users', **args)), + {'username': base.TEST_USER_ADMIN_LOGIN, + 'password': base.TEST_USER_ADMIN_PASS, '_session_csrf_secret_token': self.session_csrf_secret_token()}) assert response.status == '302 Found' for encoded in args_encoded: assert encoded in response.location - @parametrize('args,args_encoded', [ + @base.parametrize('args,args_encoded', [ ({'foo':'one', 'bar':'two'}, ('foo=one', 'bar=two')), ({'blue': u'blå', 'green':u'grøn'}, ('blue=bl%C3%A5', 'green=gr%C3%B8n')), ]) def test_login_form_after_incorrect_login_preserves_get_args(self, args, args_encoded): - response = self.app.post(url(controller='login', action='index', - came_from=url('/_admin/users', **args)), + response = self.app.post(base.url(controller='login', action='index', + came_from=base.url('/_admin/users', **args)), {'username': 'error', 'password': 'test12', '_session_csrf_secret_token': self.session_csrf_secret_token()}) response.mustcontain('Invalid username or password') - came_from = urlparse.parse_qs(urlparse.urlparse(response.form.action).query)['came_from'][0] + came_from = urllib.parse.parse_qs(urllib.parse.urlparse(response.form.action).query)['came_from'][0] for encoded in args_encoded: assert encoded in came_from @@ -224,12 +224,12 @@ # REGISTRATIONS #========================================================================== def test_register(self): - response = self.app.get(url(controller='login', action='register')) + response = self.app.get(base.url(controller='login', action='register')) response.mustcontain('Sign Up') def test_register_err_same_username(self): - uname = TEST_USER_ADMIN_LOGIN - response = self.app.post(url(controller='login', action='register'), + uname = base.TEST_USER_ADMIN_LOGIN + response = self.app.post(base.url(controller='login', action='register'), {'username': uname, 'password': 'test12', 'password_confirmation': 'test12', @@ -244,11 +244,11 @@ response.mustcontain(msg) def test_register_err_same_email(self): - response = self.app.post(url(controller='login', action='register'), + response = self.app.post(base.url(controller='login', action='register'), {'username': 'test_admin_0', 'password': 'test12', 'password_confirmation': 'test12', - 'email': TEST_USER_ADMIN_EMAIL, + 'email': base.TEST_USER_ADMIN_EMAIL, 'firstname': 'test', 'lastname': 'test', '_session_csrf_secret_token': self.session_csrf_secret_token()}) @@ -258,11 +258,11 @@ response.mustcontain(msg) def test_register_err_same_email_case_sensitive(self): - response = self.app.post(url(controller='login', action='register'), + response = self.app.post(base.url(controller='login', action='register'), {'username': 'test_admin_1', 'password': 'test12', 'password_confirmation': 'test12', - 'email': TEST_USER_ADMIN_EMAIL.title(), + 'email': base.TEST_USER_ADMIN_EMAIL.title(), 'firstname': 'test', 'lastname': 'test', '_session_csrf_secret_token': self.session_csrf_secret_token()}) @@ -271,7 +271,7 @@ response.mustcontain(msg) def test_register_err_wrong_data(self): - response = self.app.post(url(controller='login', action='register'), + response = self.app.post(base.url(controller='login', action='register'), {'username': 'xs', 'password': 'test', 'password_confirmation': 'test', @@ -284,7 +284,7 @@ response.mustcontain('Enter a value 6 characters long or more') def test_register_err_username(self): - response = self.app.post(url(controller='login', action='register'), + response = self.app.post(base.url(controller='login', action='register'), {'username': 'error user', 'password': 'test12', 'password_confirmation': 'test12', @@ -300,8 +300,8 @@ 'alphanumeric character') def test_register_err_case_sensitive(self): - usr = TEST_USER_ADMIN_LOGIN.title() - response = self.app.post(url(controller='login', action='register'), + usr = base.TEST_USER_ADMIN_LOGIN.title() + response = self.app.post(base.url(controller='login', action='register'), {'username': usr, 'password': 'test12', 'password_confirmation': 'test12', @@ -317,7 +317,7 @@ response.mustcontain(msg) def test_register_special_chars(self): - response = self.app.post(url(controller='login', action='register'), + response = self.app.post(base.url(controller='login', action='register'), {'username': 'xxxaxn', 'password': 'ąćźżąśśśś', 'password_confirmation': 'ąćźżąśśśś', @@ -331,7 +331,7 @@ response.mustcontain(msg) def test_register_password_mismatch(self): - response = self.app.post(url(controller='login', action='register'), + response = self.app.post(base.url(controller='login', action='register'), {'username': 'xs', 'password': '123qwe', 'password_confirmation': 'qwe123', @@ -350,7 +350,7 @@ name = 'testname' lastname = 'testlastname' - response = self.app.post(url(controller='login', action='register'), + response = self.app.post(base.url(controller='login', action='register'), {'username': username, 'password': password, 'password_confirmation': password, @@ -378,14 +378,14 @@ def test_forgot_password_wrong_mail(self): bad_email = 'username%wrongmail.org' response = self.app.post( - url(controller='login', action='password_reset'), + base.url(controller='login', action='password_reset'), {'email': bad_email, '_session_csrf_secret_token': self.session_csrf_secret_token()}) response.mustcontain('An email address must contain a single @') def test_forgot_password(self): - response = self.app.get(url(controller='login', + response = self.app.get(base.url(controller='login', action='password_reset')) assert response.status == '200 OK' @@ -406,26 +406,47 @@ Session().add(new) Session().commit() - response = self.app.post(url(controller='login', - action='password_reset'), - {'email': email, - '_session_csrf_secret_token': self.session_csrf_secret_token()}) + token = UserModel().get_reset_password_token( + User.get_by_username(username), timestamp, self.session_csrf_secret_token()) + + collected = [] + def mock_send_email(recipients, subject, body='', html_body='', headers=None, author=None): + collected.append((recipients, subject, body, html_body)) + + with mock.patch.object(kallithea.lib.celerylib.tasks, 'send_email', mock_send_email), \ + mock.patch.object(time, 'time', lambda: timestamp): + response = self.app.post(base.url(controller='login', + action='password_reset'), + {'email': email, + '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'A password reset confirmation code has been sent') + ((recipients, subject, body, html_body),) = collected + assert recipients == ['username@example.com'] + assert subject == 'Password reset link' + assert '\n%s\n' % token in body + (confirmation_url,) = (line for line in body.splitlines() if line.startswith('http://')) + assert ' href="%s"' % confirmation_url.replace('&', '&').replace('@', '%40') in html_body + + d = urllib.parse.parse_qs(urllib.parse.urlparse(confirmation_url).query) + assert d['token'] == [token] + assert d['timestamp'] == [str(timestamp)] + assert d['email'] == [email] + response = response.follow() # BAD TOKEN - token = "bad" + bad_token = "bad" - response = self.app.post(url(controller='login', + response = self.app.post(base.url(controller='login', action='password_reset_confirmation'), {'email': email, 'timestamp': timestamp, 'password': "p@ssw0rd", 'password_confirm': "p@ssw0rd", - 'token': token, + 'token': bad_token, '_session_csrf_secret_token': self.session_csrf_secret_token(), }) assert response.status == '200 OK' @@ -433,21 +454,17 @@ # GOOD TOKEN - # TODO: The token should ideally be taken from the mail sent - # above, instead of being recalculated. - - token = UserModel().get_reset_password_token( - User.get_by_username(username), timestamp, self.session_csrf_secret_token()) - - response = self.app.get(url(controller='login', - action='password_reset_confirmation', - email=email, - timestamp=timestamp, - token=token)) + response = self.app.get(confirmation_url) assert response.status == '200 OK' response.mustcontain("You are about to set a new password for the email address %s" % email) + response.mustcontain('
    ' % base.url(controller='login', action='password_reset_confirmation')) + response.mustcontain('value="%s"' % self.session_csrf_secret_token()) + response.mustcontain('value="%s"' % token) + response.mustcontain('value="%s"' % timestamp) + response.mustcontain('value="username@example.com"') - response = self.app.post(url(controller='login', + # fake a submit of that form + response = self.app.post(base.url(controller='login', action='password_reset_confirmation'), {'email': email, 'timestamp': timestamp, @@ -483,16 +500,16 @@ params = {'api_key': api_key} headers = {'Authorization': 'Bearer ' + str(api_key)} - self.app.get(url(controller='changeset', action='changeset_raw', - repo_name=HG_REPO, revision='tip', **params), + self.app.get(base.url(controller='changeset', action='changeset_raw', + repo_name=base.HG_REPO, revision='tip', **params), status=status) - self.app.get(url(controller='changeset', action='changeset_raw', - repo_name=HG_REPO, revision='tip'), + self.app.get(base.url(controller='changeset', action='changeset_raw', + repo_name=base.HG_REPO, revision='tip'), headers=headers, status=status) - @parametrize('test_name,api_key,code', [ + @base.parametrize('test_name,api_key,code', [ ('none', None, 302), ('empty_string', '', 403), ('fake_number', '123456', 403), @@ -504,12 +521,12 @@ self._api_key_test(api_key, code) def test_access_page_via_extra_api_key(self): - new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, u'test') + new_api_key = ApiKeyModel().create(base.TEST_USER_ADMIN_LOGIN, u'test') Session().commit() self._api_key_test(new_api_key.api_key, status=200) def test_access_page_via_expired_api_key(self): - new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, u'test') + new_api_key = ApiKeyModel().create(base.TEST_USER_ADMIN_LOGIN, u'test') Session().commit() # patch the API key and make it expired new_api_key.expires = 0 diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/functional/test_my_account.py --- a/kallithea/tests/functional/test_my_account.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/functional/test_my_account.py Thu Feb 06 01:19:23 2020 +0100 @@ -6,14 +6,14 @@ from kallithea.model.db import Repository, User, UserApiKeys, UserFollowing, UserSshKeys from kallithea.model.meta import Session from kallithea.model.user import UserModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture fixture = Fixture() -class TestMyAccountController(TestController): +class TestMyAccountController(base.TestController): test_user_1 = 'testme' @classmethod @@ -24,74 +24,74 @@ def test_my_account(self): self.log_user() - response = self.app.get(url('my_account')) + response = self.app.get(base.url('my_account')) - response.mustcontain('value="%s' % TEST_USER_ADMIN_LOGIN) + response.mustcontain('value="%s' % base.TEST_USER_ADMIN_LOGIN) def test_my_account_my_repos(self): self.log_user() - response = self.app.get(url('my_account_repos')) + response = self.app.get(base.url('my_account_repos')) cnt = Repository.query().filter(Repository.owner == - User.get_by_username(TEST_USER_ADMIN_LOGIN)).count() - response.mustcontain('"raw_name": "%s"' % HG_REPO) - response.mustcontain('"just_name": "%s"' % GIT_REPO) + User.get_by_username(base.TEST_USER_ADMIN_LOGIN)).count() + response.mustcontain('"raw_name": "%s"' % base.HG_REPO) + response.mustcontain('"just_name": "%s"' % base.GIT_REPO) def test_my_account_my_watched(self): self.log_user() - response = self.app.get(url('my_account_watched')) + response = self.app.get(base.url('my_account_watched')) cnt = UserFollowing.query().filter(UserFollowing.user == - User.get_by_username(TEST_USER_ADMIN_LOGIN)).count() - response.mustcontain('"raw_name": "%s"' % HG_REPO) - response.mustcontain('"just_name": "%s"' % GIT_REPO) + User.get_by_username(base.TEST_USER_ADMIN_LOGIN)).count() + response.mustcontain('"raw_name": "%s"' % base.HG_REPO) + response.mustcontain('"just_name": "%s"' % base.GIT_REPO) def test_my_account_my_emails(self): self.log_user() - response = self.app.get(url('my_account_emails')) + response = self.app.get(base.url('my_account_emails')) response.mustcontain('No additional emails specified') def test_my_account_my_emails_add_existing_email(self): self.log_user() - response = self.app.get(url('my_account_emails')) + response = self.app.get(base.url('my_account_emails')) response.mustcontain('No additional emails specified') - response = self.app.post(url('my_account_emails'), - {'new_email': TEST_USER_REGULAR_EMAIL, '_session_csrf_secret_token': self.session_csrf_secret_token()}) + response = self.app.post(base.url('my_account_emails'), + {'new_email': base.TEST_USER_REGULAR_EMAIL, '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'This email address is already in use') def test_my_account_my_emails_add_missing_email_in_form(self): self.log_user() - response = self.app.get(url('my_account_emails')) + response = self.app.get(base.url('my_account_emails')) response.mustcontain('No additional emails specified') - response = self.app.post(url('my_account_emails'), + response = self.app.post(base.url('my_account_emails'), {'_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'Please enter an email address') def test_my_account_my_emails_add_remove(self): self.log_user() - response = self.app.get(url('my_account_emails')) + response = self.app.get(base.url('my_account_emails')) response.mustcontain('No additional emails specified') - response = self.app.post(url('my_account_emails'), + response = self.app.post(base.url('my_account_emails'), {'new_email': 'barz@example.com', '_session_csrf_secret_token': self.session_csrf_secret_token()}) - response = self.app.get(url('my_account_emails')) + response = self.app.get(base.url('my_account_emails')) from kallithea.model.db import UserEmailMap email_id = UserEmailMap.query() \ - .filter(UserEmailMap.user == User.get_by_username(TEST_USER_ADMIN_LOGIN)) \ + .filter(UserEmailMap.user == User.get_by_username(base.TEST_USER_ADMIN_LOGIN)) \ .filter(UserEmailMap.email == 'barz@example.com').one().email_id response.mustcontain('barz@example.com') response.mustcontain('' % email_id) - response = self.app.post(url('my_account_emails_delete'), + response = self.app.post(base.url('my_account_emails_delete'), {'del_email_id': email_id, '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'Removed email from user') - response = self.app.get(url('my_account_emails')) + response = self.app.get(base.url('my_account_emails')) response.mustcontain('No additional emails specified') - @parametrize('name,attrs', + @base.parametrize('name,attrs', [('firstname', {'firstname': 'new_username'}), ('lastname', {'lastname': 'new_username'}), ('admin', {'admin': True}), @@ -123,7 +123,7 @@ params.update({'_session_csrf_secret_token': self.session_csrf_secret_token()}) params.update(attrs) - response = self.app.post(url('my_account'), params) + response = self.app.post(base.url('my_account'), params) self.checkSessionFlash(response, 'Your account was updated successfully') @@ -155,11 +155,11 @@ def test_my_account_update_err_email_exists(self): self.log_user() - new_email = TEST_USER_REGULAR_EMAIL # already existing email - response = self.app.post(url('my_account'), + new_email = base.TEST_USER_REGULAR_EMAIL # already existing email + response = self.app.post(base.url('my_account'), params=dict( - username=TEST_USER_ADMIN_LOGIN, - new_password=TEST_USER_ADMIN_PASS, + username=base.TEST_USER_ADMIN_LOGIN, + new_password=base.TEST_USER_ADMIN_PASS, password_confirmation='test122', firstname=u'NewName', lastname=u'NewLastname', @@ -170,13 +170,13 @@ response.mustcontain('This email address is already in use') def test_my_account_update_err(self): - self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) + self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS) new_email = 'newmail.pl' - response = self.app.post(url('my_account'), + response = self.app.post(base.url('my_account'), params=dict( - username=TEST_USER_ADMIN_LOGIN, - new_password=TEST_USER_ADMIN_PASS, + username=base.TEST_USER_ADMIN_LOGIN, + new_password=base.TEST_USER_ADMIN_PASS, password_confirmation='test122', firstname=u'NewName', lastname=u'NewLastname', @@ -188,25 +188,25 @@ with test_context(self.app): msg = validators.ValidUsername(edit=False, old_data={}) \ ._messages['username_exists'] - msg = h.html_escape(msg % {'username': TEST_USER_ADMIN_LOGIN}) + msg = h.html_escape(msg % {'username': base.TEST_USER_ADMIN_LOGIN}) response.mustcontain(msg) def test_my_account_api_keys(self): - usr = self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) + usr = self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS) user = User.get(usr['user_id']) - response = self.app.get(url('my_account_api_keys')) + response = self.app.get(base.url('my_account_api_keys')) response.mustcontain(user.api_key) response.mustcontain('Expires: Never') - @parametrize('desc,lifetime', [ + @base.parametrize('desc,lifetime', [ ('forever', -1), ('5mins', 60*5), ('30days', 60*60*24*30), ]) def test_my_account_add_api_keys(self, desc, lifetime): - usr = self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) + usr = self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS) user = User.get(usr['user_id']) - response = self.app.post(url('my_account_api_keys'), + response = self.app.post(base.url('my_account_api_keys'), {'description': desc, 'lifetime': lifetime, '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'API key successfully created') try: @@ -220,9 +220,9 @@ Session().commit() def test_my_account_remove_api_key(self): - usr = self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) + usr = self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS) user = User.get(usr['user_id']) - response = self.app.post(url('my_account_api_keys'), + response = self.app.post(base.url('my_account_api_keys'), {'description': 'desc', 'lifetime': -1, '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'API key successfully created') response = response.follow() @@ -231,21 +231,21 @@ keys = UserApiKeys.query().all() assert 1 == len(keys) - response = self.app.post(url('my_account_api_keys_delete'), + response = self.app.post(base.url('my_account_api_keys_delete'), {'del_api_key': keys[0].api_key, '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'API key successfully deleted') keys = UserApiKeys.query().all() assert 0 == len(keys) def test_my_account_reset_main_api_key(self): - usr = self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) + usr = self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS) user = User.get(usr['user_id']) api_key = user.api_key - response = self.app.get(url('my_account_api_keys')) + response = self.app.get(base.url('my_account_api_keys')) response.mustcontain(api_key) response.mustcontain('Expires: Never') - response = self.app.post(url('my_account_api_keys_delete'), + response = self.app.post(base.url('my_account_api_keys_delete'), {'del_api_key_builtin': api_key, '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'API key successfully reset') response = response.follow() @@ -256,8 +256,8 @@ public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost' fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8' - self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) - response = self.app.post(url('my_account_ssh_keys'), + self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS) + response = self.app.post(base.url('my_account_ssh_keys'), {'description': description, 'public_key': public_key, '_session_csrf_secret_token': self.session_csrf_secret_token()}) @@ -277,8 +277,8 @@ public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost' fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8' - self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) - response = self.app.post(url('my_account_ssh_keys'), + self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS) + response = self.app.post(base.url('my_account_ssh_keys'), {'description': description, 'public_key': public_key, '_session_csrf_secret_token': self.session_csrf_secret_token()}) @@ -288,8 +288,8 @@ ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one() assert ssh_key.description == u'me@localhost' - response = self.app.post(url('my_account_ssh_keys_delete'), - {'del_public_key': ssh_key.public_key, + response = self.app.post(base.url('my_account_ssh_keys_delete'), + {'del_public_key_fingerprint': ssh_key.fingerprint, '_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'SSH key successfully deleted') keys = UserSshKeys.query().all() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/functional/test_pullrequests.py --- a/kallithea/tests/functional/test_pullrequests.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/functional/test_pullrequests.py Thu Feb 06 01:19:23 2020 +0100 @@ -5,27 +5,27 @@ from kallithea.controllers.pullrequests import PullrequestsController from kallithea.model.db import PullRequest, User from kallithea.model.meta import Session -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture fixture = Fixture() -class TestPullrequestsController(TestController): +class TestPullrequestsController(base.TestController): def test_index(self): self.log_user() - response = self.app.get(url(controller='pullrequests', action='index', - repo_name=HG_REPO)) + response = self.app.get(base.url(controller='pullrequests', action='index', + repo_name=base.HG_REPO)) def test_create_trivial(self): self.log_user() - response = self.app.post(url(controller='pullrequests', action='create', - repo_name=HG_REPO), - {'org_repo': HG_REPO, + response = self.app.post(base.url(controller='pullrequests', action='create', + repo_name=base.HG_REPO), + {'org_repo': base.HG_REPO, 'org_ref': 'branch:stable:4f7e2131323e0749a740c0a56ab68ae9269c562a', - 'other_repo': HG_REPO, + 'other_repo': base.HG_REPO, 'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', @@ -40,11 +40,11 @@ def test_available(self): self.log_user() - response = self.app.post(url(controller='pullrequests', action='create', - repo_name=HG_REPO), - {'org_repo': HG_REPO, + response = self.app.post(base.url(controller='pullrequests', action='create', + repo_name=base.HG_REPO), + {'org_repo': base.HG_REPO, 'org_ref': 'rev:94f45ed825a1:94f45ed825a113e61af7e141f44ca578374abef0', - 'other_repo': HG_REPO, + 'other_repo': base.HG_REPO, 'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', @@ -60,11 +60,11 @@ def test_range(self): self.log_user() - response = self.app.post(url(controller='pullrequests', action='create', - repo_name=HG_REPO), - {'org_repo': HG_REPO, + response = self.app.post(base.url(controller='pullrequests', action='create', + repo_name=base.HG_REPO), + {'org_repo': base.HG_REPO, 'org_ref': 'branch:stable:4f7e2131323e0749a740c0a56ab68ae9269c562a', - 'other_repo': HG_REPO, + 'other_repo': base.HG_REPO, 'other_ref': 'rev:94f45ed825a1:94f45ed825a113e61af7e141f44ca578374abef0', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', @@ -78,57 +78,57 @@ def test_update_reviewers(self): self.log_user() - regular_user = User.get_by_username(TEST_USER_REGULAR_LOGIN) - regular_user2 = User.get_by_username(TEST_USER_REGULAR2_LOGIN) - admin_user = User.get_by_username(TEST_USER_ADMIN_LOGIN) + regular_user = User.get_by_username(base.TEST_USER_REGULAR_LOGIN) + regular_user2 = User.get_by_username(base.TEST_USER_REGULAR2_LOGIN) + admin_user = User.get_by_username(base.TEST_USER_ADMIN_LOGIN) # create initial PR - response = self.app.post(url(controller='pullrequests', action='create', - repo_name=HG_REPO), - {'org_repo': HG_REPO, + response = self.app.post(base.url(controller='pullrequests', action='create', + repo_name=base.HG_REPO), + {'org_repo': base.HG_REPO, 'org_ref': 'rev:94f45ed825a1:94f45ed825a113e61af7e141f44ca578374abef0', - 'other_repo': HG_REPO, + 'other_repo': base.HG_REPO, 'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', '_session_csrf_secret_token': self.session_csrf_secret_token(), }, status=302) - pull_request1_id = re.search('/pull-request/(\d+)/', response.location).group(1) - assert response.location == 'http://localhost/%s/pull-request/%s/_/stable' % (HG_REPO, pull_request1_id) + pull_request1_id = re.search(r'/pull-request/(\d+)/', response.location).group(1) + assert response.location == 'http://localhost/%s/pull-request/%s/_/stable' % (base.HG_REPO, pull_request1_id) # create new iteration - response = self.app.post(url(controller='pullrequests', action='post', - repo_name=HG_REPO, pull_request_id=pull_request1_id), + response = self.app.post(base.url(controller='pullrequests', action='post', + repo_name=base.HG_REPO, pull_request_id=pull_request1_id), { 'updaterev': '4f7e2131323e0749a740c0a56ab68ae9269c562a', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', - 'owner': TEST_USER_ADMIN_LOGIN, + 'owner': base.TEST_USER_ADMIN_LOGIN, '_session_csrf_secret_token': self.session_csrf_secret_token(), 'review_members': [regular_user.user_id], }, status=302) - pull_request2_id = re.search('/pull-request/(\d+)/', response.location).group(1) + pull_request2_id = re.search(r'/pull-request/(\d+)/', response.location).group(1) assert pull_request2_id != pull_request1_id - assert response.location == 'http://localhost/%s/pull-request/%s/_/stable' % (HG_REPO, pull_request2_id) + assert response.location == 'http://localhost/%s/pull-request/%s/_/stable' % (base.HG_REPO, pull_request2_id) response = response.follow() # verify reviewer was added response.mustcontain('' % regular_user.user_id) # update without creating new iteration - response = self.app.post(url(controller='pullrequests', action='post', - repo_name=HG_REPO, pull_request_id=pull_request2_id), + response = self.app.post(base.url(controller='pullrequests', action='post', + repo_name=base.HG_REPO, pull_request_id=pull_request2_id), { 'pullrequest_title': 'Title', 'pullrequest_desc': 'description', - 'owner': TEST_USER_ADMIN_LOGIN, + 'owner': base.TEST_USER_ADMIN_LOGIN, '_session_csrf_secret_token': self.session_csrf_secret_token(), 'org_review_members': [admin_user.user_id], # fake - just to get some 'meanwhile' warning ... but it is also added ... 'review_members': [regular_user2.user_id, admin_user.user_id], }, status=302) - assert response.location == 'http://localhost/%s/pull-request/%s/_/stable' % (HG_REPO, pull_request2_id) + assert response.location == 'http://localhost/%s/pull-request/%s/_/stable' % (base.HG_REPO, pull_request2_id) response = response.follow() # verify reviewers were added / removed response.mustcontain('Meanwhile, the following reviewers have been added: test_regular') @@ -141,12 +141,12 @@ invalid_user_id = 99999 self.log_user() # create a valid pull request - response = self.app.post(url(controller='pullrequests', action='create', - repo_name=HG_REPO), + response = self.app.post(base.url(controller='pullrequests', action='create', + repo_name=base.HG_REPO), { - 'org_repo': HG_REPO, + 'org_repo': base.HG_REPO, 'org_ref': 'rev:94f45ed825a1:94f45ed825a113e61af7e141f44ca578374abef0', - 'other_repo': HG_REPO, + 'other_repo': base.HG_REPO, 'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', @@ -155,34 +155,34 @@ status=302) # location is of the form: # http://localhost/vcs_test_hg/pull-request/54/_/title - m = re.search('/pull-request/(\d+)/', response.location) + m = re.search(r'/pull-request/(\d+)/', response.location) assert m is not None pull_request_id = m.group(1) # update it - response = self.app.post(url(controller='pullrequests', action='post', - repo_name=HG_REPO, pull_request_id=pull_request_id), + response = self.app.post(base.url(controller='pullrequests', action='post', + repo_name=base.HG_REPO, pull_request_id=pull_request_id), { 'updaterev': '4f7e2131323e0749a740c0a56ab68ae9269c562a', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', - 'owner': TEST_USER_ADMIN_LOGIN, + 'owner': base.TEST_USER_ADMIN_LOGIN, '_session_csrf_secret_token': self.session_csrf_secret_token(), 'review_members': [str(invalid_user_id)], }, status=400) - response.mustcontain('Invalid reviewer "%s" specified' % invalid_user_id) + response.mustcontain('Invalid reviewer "%s" specified' % invalid_user_id) def test_edit_with_invalid_reviewer(self): invalid_user_id = 99999 self.log_user() # create a valid pull request - response = self.app.post(url(controller='pullrequests', action='create', - repo_name=HG_REPO), + response = self.app.post(base.url(controller='pullrequests', action='create', + repo_name=base.HG_REPO), { - 'org_repo': HG_REPO, + 'org_repo': base.HG_REPO, 'org_ref': 'branch:stable:4f7e2131323e0749a740c0a56ab68ae9269c562a', - 'other_repo': HG_REPO, + 'other_repo': base.HG_REPO, 'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', @@ -191,22 +191,22 @@ status=302) # location is of the form: # http://localhost/vcs_test_hg/pull-request/54/_/title - m = re.search('/pull-request/(\d+)/', response.location) + m = re.search(r'/pull-request/(\d+)/', response.location) assert m is not None pull_request_id = m.group(1) # edit it - response = self.app.post(url(controller='pullrequests', action='post', - repo_name=HG_REPO, pull_request_id=pull_request_id), + response = self.app.post(base.url(controller='pullrequests', action='post', + repo_name=base.HG_REPO, pull_request_id=pull_request_id), { 'pullrequest_title': 'title', 'pullrequest_desc': 'description', - 'owner': TEST_USER_ADMIN_LOGIN, + 'owner': base.TEST_USER_ADMIN_LOGIN, '_session_csrf_secret_token': self.session_csrf_secret_token(), 'review_members': [str(invalid_user_id)], }, status=400) - response.mustcontain('Invalid reviewer "%s" specified' % invalid_user_id) + response.mustcontain('Invalid reviewer "%s" specified' % invalid_user_id) def test_iteration_refs(self): # Repo graph excerpt: @@ -226,18 +226,18 @@ # create initial PR response = self.app.post( - url(controller='pullrequests', action='create', repo_name=HG_REPO), + base.url(controller='pullrequests', action='create', repo_name=base.HG_REPO), { - 'org_repo': HG_REPO, + 'org_repo': base.HG_REPO, 'org_ref': 'rev:9e6119747791:9e6119747791ff886a5abe1193a730b6bf874e1c', - 'other_repo': HG_REPO, + 'other_repo': base.HG_REPO, 'other_ref': 'branch:default:3d1091ee5a533b1f4577ec7d8a226bb315fb1336', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', '_session_csrf_secret_token': self.session_csrf_secret_token(), }, status=302) - pr1_id = int(re.search('/pull-request/(\d+)/', response.location).group(1)) + pr1_id = int(re.search(r'/pull-request/(\d+)/', response.location).group(1)) pr1 = PullRequest.get(pr1_id) assert pr1.org_ref == 'branch:webvcs:9e6119747791ff886a5abe1193a730b6bf874e1c' @@ -247,16 +247,16 @@ # create PR 2 (new iteration with same ancestor) response = self.app.post( - url(controller='pullrequests', action='post', repo_name=HG_REPO, pull_request_id=pr1_id), + base.url(controller='pullrequests', action='post', repo_name=base.HG_REPO, pull_request_id=pr1_id), { 'updaterev': '5ec21f21aafe95220f1fc4843a4a57c378498b71', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', - 'owner': TEST_USER_REGULAR_LOGIN, + 'owner': base.TEST_USER_REGULAR_LOGIN, '_session_csrf_secret_token': self.session_csrf_secret_token(), }, status=302) - pr2_id = int(re.search('/pull-request/(\d+)/', response.location).group(1)) + pr2_id = int(re.search(r'/pull-request/(\d+)/', response.location).group(1)) pr1 = PullRequest.get(pr1_id) pr2 = PullRequest.get(pr2_id) @@ -269,16 +269,16 @@ # create PR 3 (new iteration with new ancestor) response = self.app.post( - url(controller='pullrequests', action='post', repo_name=HG_REPO, pull_request_id=pr2_id), + base.url(controller='pullrequests', action='post', repo_name=base.HG_REPO, pull_request_id=pr2_id), { 'updaterev': 'fb95b340e0d03fa51f33c56c991c08077c99303e', 'pullrequest_title': 'title', 'pullrequest_desc': 'description', - 'owner': TEST_USER_REGULAR_LOGIN, + 'owner': base.TEST_USER_REGULAR_LOGIN, '_session_csrf_secret_token': self.session_csrf_secret_token(), }, status=302) - pr3_id = int(re.search('/pull-request/(\d+)/', response.location).group(1)) + pr3_id = int(re.search(r'/pull-request/(\d+)/', response.location).group(1)) pr2 = PullRequest.get(pr2_id) pr3 = PullRequest.get(pr3_id) @@ -289,7 +289,7 @@ @pytest.mark.usefixtures("test_context_fixture") # apply fixture for all test methods -class TestPullrequestsGetRepoRefs(TestController): +class TestPullrequestsGetRepoRefs(base.TestController): def setup_method(self, method): self.repo_name = u'main' diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/functional/test_repo_groups.py --- a/kallithea/tests/functional/test_repo_groups.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/functional/test_repo_groups.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,16 +1,16 @@ -from kallithea.tests.base import * +from kallithea.tests import base -class TestRepoGroupsController(TestController): +class TestRepoGroupsController(base.TestController): def test_index(self): self.log_user() - response = self.app.get(url('repos_groups')) + response = self.app.get(base.url('repos_groups')) response.mustcontain('"records": []') def test_new(self): self.log_user() - response = self.app.get(url('new_repos_group')) + response = self.app.get(base.url('new_repos_group')) def test_create(self): self.log_user() @@ -18,14 +18,14 @@ group_name = 'foo' # creation with form error - response = self.app.post(url('repos_groups'), + response = self.app.post(base.url('repos_groups'), {'group_name': group_name, '_session_csrf_secret_token': self.session_csrf_secret_token()}) response.mustcontain('name="group_name" type="text" value="%s"' % group_name) response.mustcontain('') # creation - response = self.app.post(url('repos_groups'), + response = self.app.post(base.url('repos_groups'), {'group_name': group_name, 'group_description': 'lala', 'parent_group_id': '-1', @@ -34,18 +34,18 @@ self.checkSessionFlash(response, 'Created repository group %s' % group_name) # edit form - response = self.app.get(url('edit_repo_group', group_name=group_name)) + response = self.app.get(base.url('edit_repo_group', group_name=group_name)) response.mustcontain('>lala<') # edit with form error - response = self.app.post(url('update_repos_group', group_name=group_name), + response = self.app.post(base.url('update_repos_group', group_name=group_name), {'group_name': group_name, '_session_csrf_secret_token': self.session_csrf_secret_token()}) response.mustcontain('name="group_name" type="text" value="%s"' % group_name) response.mustcontain('') # edit - response = self.app.post(url('update_repos_group', group_name=group_name), + response = self.app.post(base.url('update_repos_group', group_name=group_name), {'group_name': group_name, 'group_description': 'lolo', '_session_csrf_secret_token': self.session_csrf_secret_token()}) @@ -56,22 +56,22 @@ response.mustcontain('>lolo<') # listing - response = self.app.get(url('repos_groups')) + response = self.app.get(base.url('repos_groups')) response.mustcontain('raw_name": "%s"' % group_name) # show - response = self.app.get(url('repos_group', group_name=group_name)) + response = self.app.get(base.url('repos_group', group_name=group_name)) response.mustcontain('href="/_admin/repo_groups/%s/edit"' % group_name) # show ignores extra trailing slashes in the URL - response = self.app.get(url('repos_group', group_name='%s//' % group_name)) + response = self.app.get(base.url('repos_group', group_name='%s//' % group_name)) response.mustcontain('href="/_admin/repo_groups/%s/edit"' % group_name) # delete - response = self.app.post(url('delete_repo_group', group_name=group_name), + response = self.app.post(base.url('delete_repo_group', group_name=group_name), {'_session_csrf_secret_token': self.session_csrf_secret_token()}) self.checkSessionFlash(response, 'Removed repository group %s' % group_name) def test_new_by_regular_user(self): - self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) - response = self.app.get(url('new_repos_group'), status=403) + self.log_user(base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR_PASS) + response = self.app.get(base.url('new_repos_group'), status=403) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/functional/test_search.py --- a/kallithea/tests/functional/test_search.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/functional/test_search.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,13 +1,13 @@ import mock -from kallithea.tests.base import * +from kallithea.tests import base -class TestSearchController(TestController): +class TestSearchController(base.TestController): def test_index(self): self.log_user() - response = self.app.get(url(controller='search', action='index')) + response = self.app.get(base.url(controller='search', action='index')) response.mustcontain('class="form-control" id="q" name="q" type="text"') # Test response... @@ -20,33 +20,33 @@ 'index_dir': str(tmpdir), } with mock.patch('kallithea.controllers.search.config', config_mock): - response = self.app.get(url(controller='search', action='index'), - {'q': HG_REPO}) + response = self.app.get(base.url(controller='search', action='index'), + {'q': base.HG_REPO}) response.mustcontain('The server has no search index.') def test_normal_search(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': 'def repo'}) response.mustcontain('58 results') def test_repo_search(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), - {'q': 'repository:%s def test' % HG_REPO}) + response = self.app.get(base.url(controller='search', action='index'), + {'q': 'repository:%s def test' % base.HG_REPO}) response.mustcontain('18 results') def test_search_last(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': 'last:t', 'type': 'commit'}) response.mustcontain('2 results') def test_search_commit_message(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': 'bother to ask where to fetch repo during tests', 'type': 'commit'}) @@ -56,8 +56,8 @@ def test_search_commit_message_hg_repo(self): self.log_user() - response = self.app.get(url(controller='search', action='index', - repo_name=HG_REPO), + response = self.app.get(base.url(controller='search', action='index', + repo_name=base.HG_REPO), {'q': 'bother to ask where to fetch repo during tests', 'type': 'commit'}) @@ -66,7 +66,7 @@ def test_search_commit_changed_file(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': 'changed:tests/utils.py', 'type': 'commit'}) @@ -74,7 +74,7 @@ def test_search_commit_changed_files_get_commit(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': 'changed:vcs/utils/archivers.py', 'type': 'commit'}) @@ -90,7 +90,7 @@ def test_search_commit_added_file(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': 'added:README.rst', 'type': 'commit'}) @@ -102,7 +102,7 @@ def test_search_author(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': 'author:marcin@python-blog.com raw_id:b986218ba1c9b0d6a259fac9b050b1724ed8e545', 'type': 'commit'}) @@ -110,7 +110,7 @@ def test_search_file_name(self): self.log_user() - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': 'README.rst', 'type': 'path'}) response.mustcontain('2 results') diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/functional/test_search_indexing.py --- a/kallithea/tests/functional/test_search_indexing.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/functional/test_search_indexing.py Thu Feb 06 01:19:23 2020 +0100 @@ -5,7 +5,7 @@ from kallithea.model.meta import Session from kallithea.model.repo import RepoModel from kallithea.model.repo_group import RepoGroupModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture, create_test_index @@ -66,10 +66,10 @@ # (FYI, ENOMEM occurs at forking "git" with python 2.7.3, # Linux 3.2.78-1 x86_64, 3GB memory, and no ulimit # configuration for memory) - create_test_index(TESTS_TMP_PATH, CONFIG, full_index=full_index) + create_test_index(base.TESTS_TMP_PATH, CONFIG, full_index=full_index) -class TestSearchControllerIndexing(TestController): +class TestSearchControllerIndexing(base.TestController): @classmethod def setup_class(cls): for reponame, init_or_fork, groupname in repos: @@ -108,7 +108,7 @@ rebuild_index(full_index=True) # rebuild fully for subsequent tests - @parametrize('reponame', [ + @base.parametrize('reponame', [ (u'indexing_test'), (u'indexing_test-fork'), (u'group/indexing_test'), @@ -116,7 +116,7 @@ (u'*-fork'), (u'group/*'), ]) - @parametrize('searchtype,query,hit', [ + @base.parametrize('searchtype,query,hit', [ ('content', 'this_should_be_unique_content', 1), ('commit', 'this_should_be_unique_commit_log', 1), ('path', 'this_should_be_unique_filename.txt', 1), @@ -125,17 +125,17 @@ self.log_user() q = 'repository:%s %s' % (reponame, query) - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': q, 'type': searchtype}) response.mustcontain('>%d results' % hit) - @parametrize('reponame', [ + @base.parametrize('reponame', [ (u'indexing_test'), (u'indexing_test-fork'), (u'group/indexing_test'), (u'this-is-it'), ]) - @parametrize('searchtype,query,hit', [ + @base.parametrize('searchtype,query,hit', [ ('content', 'this_should_be_unique_content', 1), ('commit', 'this_should_be_unique_commit_log', 1), ('path', 'this_should_be_unique_filename.txt', 1), @@ -143,12 +143,12 @@ def test_searching_under_repository(self, reponame, searchtype, query, hit): self.log_user() - response = self.app.get(url(controller='search', action='index', + response = self.app.get(base.url(controller='search', action='index', repo_name=reponame), {'q': query, 'type': searchtype}) response.mustcontain('>%d results' % hit) - @parametrize('searchtype,query,hit', [ + @base.parametrize('searchtype,query,hit', [ ('content', 'path:this/is/it def test', 1), ('commit', 'added:this/is/it bother to ask where', 1), # this condition matches against files below, because @@ -161,12 +161,12 @@ ('path', 'extension:us', 1), ]) def test_filename_stopword(self, searchtype, query, hit): - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': query, 'type': searchtype}) response.mustcontain('>%d results' % hit) - @parametrize('searchtype,query,hit', [ + @base.parametrize('searchtype,query,hit', [ # matching against both 2 files ('content', 'owner:"this is it"', 0), ('content', 'owner:this-is-it', 0), @@ -182,7 +182,7 @@ ('commit', 'author:"this-is-it"', 1), ]) def test_mailaddr_stopword(self, searchtype, query, hit): - response = self.app.get(url(controller='search', action='index'), + response = self.app.get(base.url(controller='search', action='index'), {'q': query, 'type': searchtype}) response.mustcontain('>%d results' % hit) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/functional/test_summary.py --- a/kallithea/tests/functional/test_summary.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/functional/test_summary.py Thu Feb 06 01:19:23 2020 +0100 @@ -18,7 +18,7 @@ from kallithea.model.meta import Session from kallithea.model.repo import RepoModel from kallithea.model.scm import ScmModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture @@ -32,14 +32,14 @@ ) -class TestSummaryController(TestController): +class TestSummaryController(base.TestController): def test_index_hg(self, custom_settings): self.log_user() - ID = Repository.get_by_repo_name(HG_REPO).repo_id - response = self.app.get(url(controller='summary', + ID = Repository.get_by_repo_name(base.HG_REPO).repo_id + response = self.app.get(base.url(controller='summary', action='index', - repo_name=HG_REPO)) + repo_name=base.HG_REPO)) # repo type response.mustcontain( @@ -52,24 +52,24 @@ # clone URLs response.mustcontain( '''''' % - (TEST_USER_ADMIN_LOGIN, HG_REPO) + (base.TEST_USER_ADMIN_LOGIN, base.HG_REPO) ) response.mustcontain( '''''' % - (TEST_USER_ADMIN_LOGIN, ID) + (base.TEST_USER_ADMIN_LOGIN, ID) ) response.mustcontain( '''''' % - (HG_REPO) + (base.HG_REPO) ) def test_index_git(self, custom_settings): self.log_user() - ID = Repository.get_by_repo_name(GIT_REPO).repo_id - response = self.app.get(url(controller='summary', + ID = Repository.get_by_repo_name(base.GIT_REPO).repo_id + response = self.app.get(base.url(controller='summary', action='index', - repo_name=GIT_REPO)) + repo_name=base.GIT_REPO)) # repo type response.mustcontain( @@ -82,21 +82,21 @@ # clone URLs response.mustcontain( '''''' % - (TEST_USER_ADMIN_LOGIN, GIT_REPO) + (base.TEST_USER_ADMIN_LOGIN, base.GIT_REPO) ) response.mustcontain( '''''' % - (TEST_USER_ADMIN_LOGIN, ID) + (base.TEST_USER_ADMIN_LOGIN, ID) ) response.mustcontain( '''''' % - (GIT_REPO) + (base.GIT_REPO) ) def test_index_by_id_hg(self): self.log_user() - ID = Repository.get_by_repo_name(HG_REPO).repo_id - response = self.app.get(url(controller='summary', + ID = Repository.get_by_repo_name(base.HG_REPO).repo_id + response = self.app.get(base.url(controller='summary', action='index', repo_name='_%s' % ID)) @@ -112,7 +112,7 @@ def test_index_by_repo_having_id_path_in_name_hg(self): self.log_user() fixture.create_repo(name=u'repo_1') - response = self.app.get(url(controller='summary', + response = self.app.get(base.url(controller='summary', action='index', repo_name='repo_1')) @@ -124,8 +124,8 @@ def test_index_by_id_git(self): self.log_user() - ID = Repository.get_by_repo_name(GIT_REPO).repo_id - response = self.app.get(url(controller='summary', + ID = Repository.get_by_repo_name(base.GIT_REPO).repo_id + response = self.app.get(base.url(controller='summary', action='index', repo_name='_%s' % ID)) @@ -146,14 +146,14 @@ def test_index_trending(self): self.log_user() # codes stats - self._enable_stats(HG_REPO) + self._enable_stats(base.HG_REPO) - ScmModel().mark_for_invalidation(HG_REPO) + ScmModel().mark_for_invalidation(base.HG_REPO) # generate statistics first - response = self.app.get(url(controller='summary', action='statistics', - repo_name=HG_REPO)) - response = self.app.get(url(controller='summary', action='index', - repo_name=HG_REPO)) + response = self.app.get(base.url(controller='summary', action='statistics', + repo_name=base.HG_REPO)) + response = self.app.get(base.url(controller='summary', action='index', + repo_name=base.HG_REPO)) response.mustcontain( '[["py", {"count": 68, "desc": ["Python"]}], ' '["rst", {"count": 16, "desc": ["Rst"]}], ' @@ -170,23 +170,23 @@ def test_index_statistics(self): self.log_user() # codes stats - self._enable_stats(HG_REPO) + self._enable_stats(base.HG_REPO) - ScmModel().mark_for_invalidation(HG_REPO) - response = self.app.get(url(controller='summary', action='statistics', - repo_name=HG_REPO)) + ScmModel().mark_for_invalidation(base.HG_REPO) + response = self.app.get(base.url(controller='summary', action='statistics', + repo_name=base.HG_REPO)) def test_index_trending_git(self): self.log_user() # codes stats - self._enable_stats(GIT_REPO) + self._enable_stats(base.GIT_REPO) - ScmModel().mark_for_invalidation(GIT_REPO) + ScmModel().mark_for_invalidation(base.GIT_REPO) # generate statistics first - response = self.app.get(url(controller='summary', action='statistics', - repo_name=GIT_REPO)) - response = self.app.get(url(controller='summary', action='index', - repo_name=GIT_REPO)) + response = self.app.get(base.url(controller='summary', action='statistics', + repo_name=base.GIT_REPO)) + response = self.app.get(base.url(controller='summary', action='index', + repo_name=base.GIT_REPO)) response.mustcontain( '[["py", {"count": 68, "desc": ["Python"]}], ' '["rst", {"count": 16, "desc": ["Rst"]}], ' @@ -203,8 +203,8 @@ def test_index_statistics_git(self): self.log_user() # codes stats - self._enable_stats(GIT_REPO) + self._enable_stats(base.GIT_REPO) - ScmModel().mark_for_invalidation(GIT_REPO) - response = self.app.get(url(controller='summary', action='statistics', - repo_name=GIT_REPO)) + ScmModel().mark_for_invalidation(base.GIT_REPO) + response = self.app.get(base.url(controller='summary', action='statistics', + repo_name=base.GIT_REPO)) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_changeset_status.py --- a/kallithea/tests/models/test_changeset_status.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_changeset_status.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,6 +1,6 @@ from kallithea.model.changeset_status import ChangesetStatusModel from kallithea.model.db import ChangesetStatus as CS -from kallithea.tests.base import * +from kallithea.tests import base class CSM(object): # ChangesetStatusMock @@ -9,12 +9,12 @@ self.status = status -class TestChangesetStatusCalculation(TestController): +class TestChangesetStatusCalculation(base.TestController): def setup_method(self, method): self.m = ChangesetStatusModel() - @parametrize('name,expected_result,statuses', [ + @base.parametrize('name,expected_result,statuses', [ ('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)]), diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_comments.py --- a/kallithea/tests/models/test_comments.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_comments.py Thu Feb 06 01:19:23 2020 +0100 @@ -3,10 +3,10 @@ from kallithea.model.comment import ChangesetCommentsModel from kallithea.model.db import Repository -from kallithea.tests.base import * +from kallithea.tests import base -class TestComments(TestController): +class TestComments(base.TestController): def _check_comment_count(self, repo_id, revision, expected_len_comments, expected_len_inline_comments, @@ -23,7 +23,7 @@ def test_create_delete_general_comment(self): with test_context(self.app): - repo_id = Repository.get_by_repo_name(HG_REPO).repo_id + repo_id = Repository.get_by_repo_name(base.HG_REPO).repo_id revision = '9a7b4ff9e8b40bbda72fc75f162325b9baa45cda' self._check_comment_count(repo_id, revision, @@ -32,8 +32,8 @@ text = u'a comment' new_comment = ChangesetCommentsModel().create( text=text, - repo=HG_REPO, - author=TEST_USER_REGULAR_LOGIN, + repo=base.HG_REPO, + author=base.TEST_USER_REGULAR_LOGIN, revision=revision, send_email=False) @@ -47,7 +47,7 @@ def test_create_delete_inline_comment(self): with test_context(self.app): - repo_id = Repository.get_by_repo_name(HG_REPO).repo_id + repo_id = Repository.get_by_repo_name(base.HG_REPO).repo_id revision = '9a7b4ff9e8b40bbda72fc75f162325b9baa45cda' self._check_comment_count(repo_id, revision, @@ -58,8 +58,8 @@ line_no = u'n50' new_comment = ChangesetCommentsModel().create( text=text, - repo=HG_REPO, - author=TEST_USER_REGULAR_LOGIN, + repo=base.HG_REPO, + author=base.TEST_USER_REGULAR_LOGIN, revision=revision, f_path=f_path, line_no=line_no, @@ -81,7 +81,7 @@ def test_create_delete_multiple_inline_comments(self): with test_context(self.app): - repo_id = Repository.get_by_repo_name(HG_REPO).repo_id + repo_id = Repository.get_by_repo_name(base.HG_REPO).repo_id revision = '9a7b4ff9e8b40bbda72fc75f162325b9baa45cda' self._check_comment_count(repo_id, revision, @@ -92,8 +92,8 @@ line_no = u'n50' new_comment = ChangesetCommentsModel().create( text=text, - repo=HG_REPO, - author=TEST_USER_REGULAR_LOGIN, + repo=base.HG_REPO, + author=base.TEST_USER_REGULAR_LOGIN, revision=revision, f_path=f_path, line_no=line_no, @@ -103,8 +103,8 @@ line_no2 = u'o41' new_comment2 = ChangesetCommentsModel().create( text=text2, - repo=HG_REPO, - author=TEST_USER_REGULAR_LOGIN, + repo=base.HG_REPO, + author=base.TEST_USER_REGULAR_LOGIN, revision=revision, f_path=f_path, line_no=line_no2, @@ -115,8 +115,8 @@ line_no3 = u'n159' new_comment3 = ChangesetCommentsModel().create( text=text3, - repo=HG_REPO, - author=TEST_USER_REGULAR_LOGIN, + repo=base.HG_REPO, + author=base.TEST_USER_REGULAR_LOGIN, revision=revision, f_path=f_path3, line_no=line_no3, @@ -126,15 +126,15 @@ expected_len_comments=0, expected_len_inline_comments=2) # inline_comments is a list of tuples (file_path, dict) # where the dict keys are line numbers and values are lists of comments - assert inline_comments[1][0] == f_path - assert len(inline_comments[1][1]) == 2 - assert inline_comments[1][1][line_no][0].text == text - assert inline_comments[1][1][line_no2][0].text == text2 + assert inline_comments[0][0] == f_path + assert len(inline_comments[0][1]) == 2 + assert inline_comments[0][1][line_no][0].text == text + assert inline_comments[0][1][line_no2][0].text == text2 - assert inline_comments[0][0] == f_path3 - assert len(inline_comments[0][1]) == 1 - assert line_no3 in inline_comments[0][1] - assert inline_comments[0][1][line_no3][0].text == text3 + assert inline_comments[1][0] == f_path3 + assert len(inline_comments[1][1]) == 1 + assert line_no3 in inline_comments[1][1] + assert inline_comments[1][1][line_no3][0].text == text3 # now delete only one comment ChangesetCommentsModel().delete(new_comment2) @@ -143,14 +143,14 @@ expected_len_comments=0, expected_len_inline_comments=2) # inline_comments is a list of tuples (file_path, dict) # where the dict keys are line numbers and values are lists of comments - assert inline_comments[1][0] == f_path - assert len(inline_comments[1][1]) == 1 - assert inline_comments[1][1][line_no][0].text == text + assert inline_comments[0][0] == f_path + assert len(inline_comments[0][1]) == 1 + assert inline_comments[0][1][line_no][0].text == text - assert inline_comments[0][0] == f_path3 - assert len(inline_comments[0][1]) == 1 - assert line_no3 in inline_comments[0][1] - assert inline_comments[0][1][line_no3][0].text == text3 + assert inline_comments[1][0] == f_path3 + assert len(inline_comments[1][1]) == 1 + assert line_no3 in inline_comments[1][1] + assert inline_comments[1][1][line_no3][0].text == text3 # now delete all others ChangesetCommentsModel().delete(new_comment) @@ -161,7 +161,7 @@ def test_selective_retrieval_of_inline_comments(self): with test_context(self.app): - repo_id = Repository.get_by_repo_name(HG_REPO).repo_id + repo_id = Repository.get_by_repo_name(base.HG_REPO).repo_id revision = '9a7b4ff9e8b40bbda72fc75f162325b9baa45cda' self._check_comment_count(repo_id, revision, @@ -172,8 +172,8 @@ line_no = u'n50' new_comment = ChangesetCommentsModel().create( text=text, - repo=HG_REPO, - author=TEST_USER_REGULAR_LOGIN, + repo=base.HG_REPO, + author=base.TEST_USER_REGULAR_LOGIN, revision=revision, f_path=f_path, line_no=line_no, @@ -183,8 +183,8 @@ line_no2 = u'o41' new_comment2 = ChangesetCommentsModel().create( text=text2, - repo=HG_REPO, - author=TEST_USER_REGULAR_LOGIN, + repo=base.HG_REPO, + author=base.TEST_USER_REGULAR_LOGIN, revision=revision, f_path=f_path, line_no=line_no2, @@ -195,8 +195,8 @@ line_no3 = u'n159' new_comment3 = ChangesetCommentsModel().create( text=text3, - repo=HG_REPO, - author=TEST_USER_REGULAR_LOGIN, + repo=base.HG_REPO, + author=base.TEST_USER_REGULAR_LOGIN, revision=revision, f_path=f_path3, line_no=line_no3, diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_diff_parsers.py --- a/kallithea/tests/models/test_diff_parsers.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_diff_parsers.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,5 +1,5 @@ from kallithea.lib.diffs import BIN_FILENODE, CHMOD_FILENODE, COPIED_FILENODE, DEL_FILENODE, MOD_FILENODE, NEW_FILENODE, RENAMED_FILENODE, DiffProcessor -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture @@ -271,9 +271,9 @@ } -class TestDiffLib(TestController): +class TestDiffLib(base.TestController): - @parametrize('diff_fixture', DIFF_FIXTURES) + @base.parametrize('diff_fixture', DIFF_FIXTURES) def test_diff(self, diff_fixture): raw_diff = fixture.load_resource(diff_fixture, strip=False) vcs = 'hg' @@ -295,20 +295,20 @@ l.append('%(action)-7s %(new_lineno)3s %(old_lineno)3s %(line)r\n' % d) s = ''.join(l) assert s == r''' -context ... ... u'@@ -51,6 +51,13 @@\n' -unmod 51 51 u'\tbegin();\n' -unmod 52 52 u'\t\n' -add 53 u'\tint foo;\n' -add 54 u'\tint bar; \n' -add 55 u'\tint baz;\t\n' -add 56 u'\tint space; ' -add 57 u'\tint tab;\t\n' -add 58 u'\t\n' -unmod 59 53 u' ' -del 54 u'\t#define MAX_STEPS (48)\n' -add 60 u'\t\n' -add 61 u'\t#define MAX_STEPS (64)\n' -unmod 62 55 u'\n' -del 56 u'\t#define MIN_STEPS (48)\n' -add 63 u'\t#define MIN_STEPS (42)\n' +context ... ... '@@ -51,6 +51,13 @@\n' +unmod 51 51 '\tbegin();\n' +unmod 52 52 '\t\n' +add 53 '\tint foo;\n' +add 54 '\tint bar; \n' +add 55 '\tint baz;\t\n' +add 56 '\tint space; ' +add 57 '\tint tab;\t\n' +add 58 '\t\n' +unmod 59 53 ' ' +del 54 '\t#define MAX_STEPS (48)\n' +add 60 '\t\n' +add 61 '\t#define MAX_STEPS (64)\n' +unmod 62 55 '\n' +del 56 '\t#define MIN_STEPS (48)\n' +add 63 '\t#define MIN_STEPS (42)\n' ''' diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_notifications.py --- a/kallithea/tests/models/test_notifications.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_notifications.py Thu Feb 06 01:19:23 2020 +0100 @@ -11,10 +11,10 @@ from kallithea.model.meta import Session from kallithea.model.notification import EmailNotificationModel, NotificationModel from kallithea.model.user import UserModel -from kallithea.tests.base import * +from kallithea.tests import base -class TestNotifications(TestController): +class TestNotifications(base.TestController): def setup_method(self, method): Session.remove() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_permissions.py --- a/kallithea/tests/models/test_permissions.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_permissions.py Thu Feb 06 01:19:23 2020 +0100 @@ -6,14 +6,14 @@ from kallithea.model.repo_group import RepoGroupModel from kallithea.model.user import UserModel from kallithea.model.user_group import UserGroupModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture fixture = Fixture() -class TestPermissions(TestController): +class TestPermissions(base.TestController): @classmethod def setup_class(cls): @@ -71,33 +71,33 @@ 'repositories_groups': {}, 'global': set(['hg.create.repository', 'repository.read', 'hg.register.manual_activate']), - 'repositories': {HG_REPO: 'repository.read'} + 'repositories': {base.HG_REPO: 'repository.read'} } - assert u1_auth.permissions['repositories'][HG_REPO] == perms['repositories'][HG_REPO] + assert u1_auth.permissions['repositories'][base.HG_REPO] == perms['repositories'][base.HG_REPO] new_perm = 'repository.write' - RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, + RepoModel().grant_user_permission(repo=base.HG_REPO, user=self.u1, perm=new_perm) Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) - assert u1_auth.permissions['repositories'][HG_REPO] == new_perm + assert u1_auth.permissions['repositories'][base.HG_REPO] == new_perm def test_default_admin_perms_set(self): a1_auth = AuthUser(user_id=self.a1.user_id) perms = { 'repositories_groups': {}, 'global': set(['hg.admin', 'hg.create.write_on_repogroup.true']), - 'repositories': {HG_REPO: 'repository.admin'} + 'repositories': {base.HG_REPO: 'repository.admin'} } - assert a1_auth.permissions['repositories'][HG_REPO] == perms['repositories'][HG_REPO] + assert a1_auth.permissions['repositories'][base.HG_REPO] == perms['repositories'][base.HG_REPO] new_perm = 'repository.write' - RepoModel().grant_user_permission(repo=HG_REPO, user=self.a1, + RepoModel().grant_user_permission(repo=base.HG_REPO, user=self.a1, perm=new_perm) Session().commit() # cannot really downgrade admins permissions !? they still gets set as # admin ! u1_auth = AuthUser(user_id=self.a1.user_id) - assert u1_auth.permissions['repositories'][HG_REPO] == perms['repositories'][HG_REPO] + assert u1_auth.permissions['repositories'][base.HG_REPO] == perms['repositories'][base.HG_REPO] def test_default_group_perms(self): self.g1 = fixture.create_repo_group(u'test1', skip_if_exists=True) @@ -106,9 +106,9 @@ perms = { 'repositories_groups': {u'test1': 'group.read', u'test2': 'group.read'}, 'global': set(Permission.DEFAULT_USER_PERMISSIONS), - 'repositories': {HG_REPO: 'repository.read'} + 'repositories': {base.HG_REPO: 'repository.read'} } - assert u1_auth.permissions['repositories'][HG_REPO] == perms['repositories'][HG_REPO] + assert u1_auth.permissions['repositories'][base.HG_REPO] == perms['repositories'][base.HG_REPO] assert u1_auth.permissions['repositories_groups'] == perms['repositories_groups'] assert u1_auth.permissions['global'] == perms['global'] @@ -119,10 +119,10 @@ perms = { 'repositories_groups': {u'test1': 'group.admin', u'test2': 'group.admin'}, 'global': set(['hg.admin', 'hg.create.write_on_repogroup.true']), - 'repositories': {HG_REPO: 'repository.admin'} + 'repositories': {base.HG_REPO: 'repository.admin'} } - assert a1_auth.permissions['repositories'][HG_REPO] == perms['repositories'][HG_REPO] + assert a1_auth.permissions['repositories'][base.HG_REPO] == perms['repositories'][base.HG_REPO] assert a1_auth.permissions['repositories_groups'] == perms['repositories_groups'] def test_propagated_permission_from_users_group_by_explicit_perms_exist(self): @@ -131,19 +131,19 @@ UserGroupModel().add_user_to_group(self.ug1, self.u1) # set user permission none - RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm='repository.none') + RepoModel().grant_user_permission(repo=base.HG_REPO, user=self.u1, perm='repository.none') Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) - assert u1_auth.permissions['repositories'][HG_REPO] == 'repository.read' # inherit from default user + assert u1_auth.permissions['repositories'][base.HG_REPO] == 'repository.read' # inherit from default user # grant perm for group this should override permission from user - RepoModel().grant_user_group_permission(repo=HG_REPO, + RepoModel().grant_user_group_permission(repo=base.HG_REPO, group_name=self.ug1, perm='repository.write') # verify that user group permissions win u1_auth = AuthUser(user_id=self.u1.user_id) - assert u1_auth.permissions['repositories'][HG_REPO] == 'repository.write' + assert u1_auth.permissions['repositories'][base.HG_REPO] == 'repository.write' def test_propagated_permission_from_users_group(self): # make group @@ -152,7 +152,7 @@ # grant perm for group this should override default permission from user new_perm_gr = 'repository.write' - RepoModel().grant_user_group_permission(repo=HG_REPO, + RepoModel().grant_user_group_permission(repo=base.HG_REPO, group_name=self.ug1, perm=new_perm_gr) # check perms @@ -161,9 +161,9 @@ 'repositories_groups': {}, 'global': set(['hg.create.repository', 'repository.read', 'hg.register.manual_activate']), - 'repositories': {HG_REPO: 'repository.read'} + 'repositories': {base.HG_REPO: 'repository.read'} } - assert u3_auth.permissions['repositories'][HG_REPO] == new_perm_gr + assert u3_auth.permissions['repositories'][base.HG_REPO] == new_perm_gr assert u3_auth.permissions['repositories_groups'] == perms['repositories_groups'] def test_propagated_permission_from_users_group_lower_weight(self): @@ -174,16 +174,16 @@ # set permission to lower new_perm_h = 'repository.write' - RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, + RepoModel().grant_user_permission(repo=base.HG_REPO, user=self.u1, perm=new_perm_h) Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) - assert u1_auth.permissions['repositories'][HG_REPO] == new_perm_h + assert u1_auth.permissions['repositories'][base.HG_REPO] == new_perm_h # grant perm for group this should NOT override permission from user # since it's lower than granted new_perm_l = 'repository.read' - RepoModel().grant_user_group_permission(repo=HG_REPO, + RepoModel().grant_user_group_permission(repo=base.HG_REPO, group_name=self.ug1, perm=new_perm_l) # check perms @@ -192,9 +192,9 @@ 'repositories_groups': {}, 'global': set(['hg.create.repository', 'repository.read', 'hg.register.manual_activate']), - 'repositories': {HG_REPO: 'repository.write'} + 'repositories': {base.HG_REPO: 'repository.write'} } - assert u1_auth.permissions['repositories'][HG_REPO] == new_perm_h + assert u1_auth.permissions['repositories'][base.HG_REPO] == new_perm_h assert u1_auth.permissions['repositories_groups'] == perms['repositories_groups'] def test_repo_in_group_permissions(self): @@ -641,7 +641,7 @@ PermissionModel().create_default_permissions(user=self.u1) self._test_def_perm_equal(user=self.u1) - @parametrize('perm,modify_to', [ + @base.parametrize('perm,modify_to', [ ('repository.read', 'repository.none'), ('group.read', 'group.none'), ('usergroup.read', 'usergroup.none'), diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_repo_groups.py --- a/kallithea/tests/models/test_repo_groups.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_repo_groups.py Thu Feb 06 01:19:23 2020 +0100 @@ -7,7 +7,7 @@ from kallithea.model.meta import Session from kallithea.model.repo import RepoModel from kallithea.model.repo_group import RepoGroupModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture @@ -34,7 +34,7 @@ return r -class TestRepoGroups(TestController): +class TestRepoGroups(base.TestController): def setup_method(self, method): self.g1 = fixture.create_repo_group(u'test1', skip_if_exists=True) @@ -48,7 +48,7 @@ """ Checks the path for existence ! """ - path = [TESTS_TMP_PATH] + list(path) + path = [base.TESTS_TMP_PATH] + list(path) path = os.path.join(*path) return os.path.isdir(path) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_repos.py --- a/kallithea/tests/models/test_repos.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_repos.py Thu Feb 06 01:19:23 2020 +0100 @@ -4,14 +4,14 @@ from kallithea.model.db import Repository from kallithea.model.meta import Session from kallithea.model.repo import RepoModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture fixture = Fixture() -class TestRepos(TestController): +class TestRepos(base.TestController): def teardown_method(self, method): Session.remove() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_settings.py --- a/kallithea/tests/models/test_settings.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_settings.py Thu Feb 06 01:19:23 2020 +0100 @@ -39,8 +39,8 @@ # Assign back setting value. setting.app_settings_value = setting.app_settings_value # Quirk: value is stringified on write and listified on read. - assert setting.app_settings_value == ["[u'spam']"] + assert setting.app_settings_value == ["['spam']"] setting.app_settings_value = setting.app_settings_value - assert setting.app_settings_value == ["[u\"[u'spam']\"]"] + assert setting.app_settings_value == ["[\"['spam']\"]"] finally: Session().delete(setting) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_user_groups.py --- a/kallithea/tests/models/test_user_groups.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_user_groups.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,14 +1,14 @@ from kallithea.model.db import User, UserGroup from kallithea.model.meta import Session from kallithea.model.user_group import UserGroupModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture fixture = Fixture() -class TestUserGroups(TestController): +class TestUserGroups(base.TestController): def teardown_method(self, method): # delete all groups @@ -16,7 +16,7 @@ fixture.destroy_user_group(gr) Session().commit() - @parametrize('pre_existing,regular_should_be,external_should_be,groups,expected', [ + @base.parametrize('pre_existing,regular_should_be,external_should_be,groups,expected', [ ([], [], [], [], []), ([], [u'regular'], [], [], [u'regular']), # no changes of regular ([u'some_other'], [], [], [u'some_other'], []), # not added to regular group @@ -32,7 +32,7 @@ fixture.destroy_user_group(gr) Session().commit() - user = User.get_by_username(TEST_USER_REGULAR_LOGIN) + user = User.get_by_username(base.TEST_USER_REGULAR_LOGIN) for gr in pre_existing: gr = fixture.create_user_group(gr) Session().commit() @@ -54,6 +54,6 @@ UserGroupModel().enforce_groups(user, groups, 'container') Session().commit() - user = User.get_by_username(TEST_USER_REGULAR_LOGIN) + user = User.get_by_username(base.TEST_USER_REGULAR_LOGIN) in_groups = user.group_member - assert expected == [x.users_group.users_group_name for x in in_groups] + assert sorted(expected) == sorted(x.users_group.users_group_name for x in in_groups) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/models/test_users.py --- a/kallithea/tests/models/test_users.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/models/test_users.py Thu Feb 06 01:19:23 2020 +0100 @@ -4,14 +4,14 @@ from kallithea.model.meta import Session from kallithea.model.user import UserModel from kallithea.model.user_group import UserGroupModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture fixture = Fixture() -class TestUser(TestController): +class TestUser(base.TestController): @classmethod def setup_class(cls): @@ -101,7 +101,7 @@ Session().commit() -class TestUsers(TestController): +class TestUsers(base.TestController): def setup_method(self, method): self.u1 = UserModel().create_or_update(username=u'u1', diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/other/test_libs.py --- a/kallithea/tests/other/test_libs.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/other/test_libs.py Thu Feb 06 01:19:23 2020 +0100 @@ -31,9 +31,9 @@ import mock from tg.util.webtest import test_context -from kallithea.lib.utils2 import AttributeDict +from kallithea.lib.utils2 import AttributeDict, safe_bytes from kallithea.model.db import Repository -from kallithea.tests.base import * +from kallithea.tests import base proto = 'http' @@ -91,19 +91,19 @@ return self.current_url % kwargs -class TestLibs(TestController): +class TestLibs(base.TestController): - @parametrize('test_url,expected,expected_creds', TEST_URLS) + @base.parametrize('test_url,expected,expected_creds', TEST_URLS) def test_uri_filter(self, test_url, expected, expected_creds): from kallithea.lib.utils2 import uri_filter assert uri_filter(test_url) == expected - @parametrize('test_url,expected,expected_creds', TEST_URLS) + @base.parametrize('test_url,expected,expected_creds', TEST_URLS) def test_credentials_filter(self, test_url, expected, expected_creds): from kallithea.lib.utils2 import credentials_filter assert credentials_filter(test_url) == expected_creds - @parametrize('str_bool,expected', [ + @base.parametrize('str_bool,expected', [ ('t', True), ('true', True), ('y', True), @@ -141,7 +141,7 @@ 'marian.user', 'marco-polo', 'marco_polo', 'world']) assert expected == set(extract_mentioned_usernames(sample)) - @parametrize('age_args,expected', [ + @base.parametrize('age_args,expected', [ (dict(), u'just now'), (dict(seconds= -1), u'1 second ago'), (dict(seconds= -60 * 2), u'2 minutes ago'), @@ -165,7 +165,7 @@ delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) assert age(n + delt(**age_args), now=n) == expected - @parametrize('age_args,expected', [ + @base.parametrize('age_args,expected', [ (dict(), u'just now'), (dict(seconds= -1), u'1 second ago'), (dict(seconds= -60 * 2), u'2 minutes ago'), @@ -190,7 +190,7 @@ delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) assert age(n + delt(**age_args), show_short_version=True, now=n) == expected - @parametrize('age_args,expected', [ + @base.parametrize('age_args,expected', [ (dict(), u'just now'), (dict(seconds=1), u'in 1 second'), (dict(seconds=60 * 2), u'in 2 minutes'), @@ -227,7 +227,7 @@ def test_alternative_gravatar(self): from kallithea.lib.helpers import gravatar_url - _md5 = lambda s: hashlib.md5(s).hexdigest() + _md5 = lambda s: hashlib.md5(safe_bytes(s)).hexdigest() # mock tg.tmpl_context def fake_tmpl_context(_url): @@ -270,7 +270,7 @@ grav = gravatar_url(email_address=em, size=24) assert grav == 'https://example.com/%s/%s' % (_md5(em), 24) - @parametrize('clone_uri_tmpl,repo_name,username,prefix,expected', [ + @base.parametrize('clone_uri_tmpl,repo_name,username,prefix,expected', [ (Repository.DEFAULT_CLONE_URI, 'group/repo1', None, '', 'http://vps1:8000/group/repo1'), (Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '', 'http://username@vps1:8000/group/repo1'), (Repository.DEFAULT_CLONE_URI, 'group/repo1', None, '/prefix', 'http://vps1:8000/prefix/group/repo1'), @@ -307,7 +307,7 @@ return tmpl % (url_ or '/repo_name/changeset/%s' % _url, _url) return url_pattern.sub(url_func, text) - @parametrize('sample,expected', [ + @base.parametrize('sample,expected', [ ("", ""), ("git-svn-id: https://svn.apache.org/repos/asf/libcloud/trunk@1441655 13f79535-47bb-0310-9956-ffa450edef68", @@ -341,7 +341,7 @@ from kallithea.lib.helpers import urlify_text assert urlify_text(sample, 'repo_name') == expected - @parametrize('sample,expected,url_', [ + @base.parametrize('sample,expected,url_', [ ("", "", ""), @@ -396,7 +396,7 @@ from kallithea.lib.helpers import urlify_text assert urlify_text(sample, 'repo_name', stylize=True) == expected - @parametrize('sample,expected', [ + @base.parametrize('sample,expected', [ ("deadbeefcafe @mention, and http://foo.bar/ yo", """deadbeefcafe""" """ @mention, and """ @@ -409,7 +409,7 @@ from kallithea.lib.helpers import urlify_text assert urlify_text(sample, 'repo_name', link_='#the-link') == expected - @parametrize('issue_pat,issue_server,issue_sub,sample,expected', [ + @base.parametrize('issue_pat,issue_server,issue_sub,sample,expected', [ (r'#(\d+)', 'http://foo/{repo}/issue/\\1', '#\\1', 'issue #123 and issue#456', """issue #123 and """ @@ -482,7 +482,7 @@ """empty issue_sub $123 and """ """issue$456"""), # named groups - (r'(PR|pullrequest|pull request) ?(?PBRU|CPH|BER)-(?P\d+)', 'http://foo/\g/pullrequest/\g/', 'PR-\g-\g', + (r'(PR|pullrequest|pull request) ?(?PBRU|CPH|BER)-(?P\d+)', r'http://foo/\g/pullrequest/\g/', r'PR-\g-\g', 'pullrequest CPH-789 is similar to PRBRU-747', """PR-CPH-789 is similar to """ """PR-BRU-747"""), @@ -500,7 +500,7 @@ with mock.patch('kallithea.CONFIG', config_stub): assert urlify_text(sample, 'repo_name') == expected - @parametrize('sample,expected', [ + @base.parametrize('sample,expected', [ ('abc X5', 'abc #5'), ('abc pullrequest #6 xyz', 'abc PR#6 xyz'), ('pull request7 #', 'PR#7 #'), @@ -512,28 +512,28 @@ def test_urlify_issues_multiple_issue_patterns(self, sample, expected): from kallithea.lib.helpers import urlify_text config_stub = { - 'sqlalchemy.url': 'foo', - 'issue_pat': 'X(\d+)', - 'issue_server_link': 'http://main/{repo}/main/\\1/', - 'issue_sub': '#\\1', - 'issue_pat_pr': '(?:pullrequest|pull request|PR|pr) ?#?(\d+)', - 'issue_server_link_pr': 'http://pr/{repo}/pr/\\1', - 'issue_sub_pr': 'PR#\\1', - 'issue_pat_bug': '(?:BUG|bug|issue) ?#?(\d+)', - 'issue_server_link_bug': 'http://bug/{repo}/bug/\\1', - 'issue_sub_bug': 'bug#\\1', - 'issue_pat_empty_prefix': 'FAIL(\d+)', - 'issue_server_link_empty_prefix': 'http://fail/{repo}/\\1', - 'issue_sub_empty_prefix': '', - 'issue_pat_absent_prefix': 'FAILMORE(\d+)', - 'issue_server_link_absent_prefix': 'http://failmore/{repo}/\\1', + 'sqlalchemy.url': r'foo', + 'issue_pat': r'X(\d+)', + 'issue_server_link': r'http://main/{repo}/main/\1/', + 'issue_sub': r'#\1', + 'issue_pat_pr': r'(?:pullrequest|pull request|PR|pr) ?#?(\d+)', + 'issue_server_link_pr': r'http://pr/{repo}/pr/\1', + 'issue_sub_pr': r'PR#\1', + 'issue_pat_bug': r'(?:BUG|bug|issue) ?#?(\d+)', + 'issue_server_link_bug': r'http://bug/{repo}/bug/\1', + 'issue_sub_bug': r'bug#\1', + 'issue_pat_empty_prefix': r'FAIL(\d+)', + 'issue_server_link_empty_prefix': r'http://fail/{repo}/\1', + 'issue_sub_empty_prefix': r'', + 'issue_pat_absent_prefix': r'FAILMORE(\d+)', + 'issue_server_link_absent_prefix': r'http://failmore/{repo}/\1', } # force recreation of lazy function with mock.patch('kallithea.lib.helpers._urlify_issues_f', None): with mock.patch('kallithea.CONFIG', config_stub): assert urlify_text(sample, 'repo_name') == expected - @parametrize('test,expected', [ + @base.parametrize('test,expected', [ ("", None), ("/_2", None), ("_2", 2), @@ -542,9 +542,9 @@ def test_get_permanent_id(self, test, expected): from kallithea.lib.utils import _get_permanent_id extracted = _get_permanent_id(test) - assert extracted == expected, 'url:%s, got:`%s` expected: `%s`' % (test, _test, expected) + assert extracted == expected, 'url:%s, got:`%s` expected: `%s`' % (test, base._test, expected) - @parametrize('test,expected', [ + @base.parametrize('test,expected', [ ("", ""), ("/", "/"), ("/_ID", '/_ID'), @@ -555,14 +555,14 @@ ("_IDa", '_IDa'), ]) def test_fix_repo_id_name(self, test, expected): - repo = Repository.get_by_repo_name(HG_REPO) + repo = Repository.get_by_repo_name(base.HG_REPO) test = test.replace('ID', str(repo.repo_id)) expected = expected.replace('NAME', repo.repo_name).replace('ID', str(repo.repo_id)) from kallithea.lib.utils import fix_repo_id_name replaced = fix_repo_id_name(test) assert replaced == expected, 'url:%s, got:`%s` expected: `%s`' % (test, replaced, expected) - @parametrize('canonical,test,expected', [ + @base.parametrize('canonical,test,expected', [ ('http://www.example.org/', '/abc/xyz', 'http://www.example.org/abc/xyz'), ('http://www.example.org', '/abc/xyz', 'http://www.example.org/abc/xyz'), ('http://www.example.org', '/abc/xyz/', 'http://www.example.org/abc/xyz/'), @@ -590,7 +590,7 @@ with mock.patch('kallithea.CONFIG', config_mock): assert canonical_url(test) == expected - @parametrize('canonical,expected', [ + @base.parametrize('canonical,expected', [ ('http://www.example.org', 'www.example.org'), ('http://www.example.org/repos/', 'www.example.org'), ('http://www.example.org/kallithea/repos/', 'www.example.org'), diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/other/test_mail.py --- a/kallithea/tests/other/test_mail.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/other/test_mail.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,8 +1,10 @@ +# -*- coding: utf-8 -*- + import mock import kallithea from kallithea.model.db import User -from kallithea.tests.base import * +from kallithea.tests import base class smtplib_mock(object): @@ -25,7 +27,7 @@ @mock.patch('kallithea.lib.rcmail.smtp_mailer.smtplib', smtplib_mock) -class TestMail(TestController): +class TestMail(base.TestController): def test_send_mail_trivial(self): mailserver = 'smtp.mailserver.org' @@ -66,7 +68,7 @@ with mock.patch('kallithea.lib.celerylib.tasks.config', config_mock): kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body) - assert smtplib_mock.lastdest == set([TEST_USER_ADMIN_EMAIL, email_to]) + assert smtplib_mock.lastdest == set([base.TEST_USER_ADMIN_EMAIL, email_to]) assert smtplib_mock.lastsender == envelope_from assert 'From: %s' % envelope_from in smtplib_mock.lastmsg assert 'Subject: %s' % subject in smtplib_mock.lastmsg @@ -90,7 +92,7 @@ with mock.patch('kallithea.lib.celerylib.tasks.config', config_mock): kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body) - assert smtplib_mock.lastdest == set([TEST_USER_ADMIN_EMAIL] + email_to.split(',')) + assert smtplib_mock.lastdest == set([base.TEST_USER_ADMIN_EMAIL] + email_to.split(',')) assert smtplib_mock.lastsender == envelope_from assert 'From: %s' % envelope_from in smtplib_mock.lastmsg assert 'Subject: %s' % subject in smtplib_mock.lastmsg @@ -112,7 +114,7 @@ with mock.patch('kallithea.lib.celerylib.tasks.config', config_mock): kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body) - assert smtplib_mock.lastdest == set([TEST_USER_ADMIN_EMAIL]) + assert smtplib_mock.lastdest == set([base.TEST_USER_ADMIN_EMAIL]) assert smtplib_mock.lastsender == envelope_from assert 'From: %s' % envelope_from in smtplib_mock.lastmsg assert 'Subject: %s' % subject in smtplib_mock.lastmsg @@ -126,7 +128,7 @@ subject = 'subject' body = 'body' html_body = 'html_body' - author = User.get_by_username(TEST_USER_REGULAR_LOGIN) + author = User.get_by_username(base.TEST_USER_REGULAR_LOGIN) config_mock = { 'smtp_server': mailserver, @@ -144,13 +146,13 @@ def test_send_mail_with_author_full_mail_from(self): mailserver = 'smtp.mailserver.org' - recipients = ['rcpt1', 'rcpt2'] + recipients = ['ræcpt1', 'receptor2 ', 'tæst@example.com', 'Tæst '] envelope_addr = 'noreply@mailserver.org' - envelope_from = 'Some Name <%s>' % envelope_addr + envelope_from = 'Söme Næme <%s>' % envelope_addr subject = 'subject' body = 'body' html_body = 'html_body' - author = User.get_by_username(TEST_USER_REGULAR_LOGIN) + author = User.get_by_username(base.TEST_USER_REGULAR_LOGIN) config_mock = { 'smtp_server': mailserver, diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/other/test_validators.py --- a/kallithea/tests/other/test_validators.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/other/test_validators.py Thu Feb 06 01:19:23 2020 +0100 @@ -6,7 +6,7 @@ from kallithea.model.meta import Session from kallithea.model.repo_group import RepoGroupModel from kallithea.model.user_group import UserGroupModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture @@ -14,7 +14,7 @@ @pytest.mark.usefixtures("test_context_fixture") # apply fixture for all test methods -class TestRepoGroups(TestController): +class TestRepoGroups(base.TestController): def teardown_method(self, method): Session.remove() @@ -40,7 +40,7 @@ with pytest.raises(formencode.Invalid): validator.to_python('.,') with pytest.raises(formencode.Invalid): - validator.to_python(TEST_USER_ADMIN_LOGIN) + validator.to_python(base.TEST_USER_ADMIN_LOGIN) assert 'test' == validator.to_python('test') validator = v.ValidUsername(edit=True, old_data={'user_id': 1}) @@ -49,7 +49,7 @@ validator = v.ValidRepoUser() with pytest.raises(formencode.Invalid): validator.to_python('nouser') - assert TEST_USER_ADMIN_LOGIN == validator.to_python(TEST_USER_ADMIN_LOGIN) + assert base.TEST_USER_ADMIN_LOGIN == validator.to_python(base.TEST_USER_ADMIN_LOGIN) def test_ValidUserGroup(self): validator = v.ValidUserGroup() @@ -82,11 +82,11 @@ validator = v.ValidRepoGroup() model = RepoGroupModel() with pytest.raises(formencode.Invalid): - validator.to_python({'group_name': HG_REPO, }) + validator.to_python({'group_name': base.HG_REPO, }) gr = model.create(group_name=u'test_gr', group_description=u'desc', parent=None, just_db=True, - owner=TEST_USER_ADMIN_LOGIN) + owner=base.TEST_USER_ADMIN_LOGIN) with pytest.raises(formencode.Invalid): validator.to_python({'group_name': gr.group_name, }) @@ -127,8 +127,8 @@ def test_ValidAuth(self): validator = v.ValidAuth() valid_creds = { - 'username': TEST_USER_REGULAR2_LOGIN, - 'password': TEST_USER_REGULAR2_PASS, + 'username': base.TEST_USER_REGULAR2_LOGIN, + 'password': base.TEST_USER_REGULAR2_PASS, } invalid_creds = { 'username': 'err', @@ -145,12 +145,12 @@ validator.to_python({'repo_name': ''}) with pytest.raises(formencode.Invalid): - validator.to_python({'repo_name': HG_REPO}) + validator.to_python({'repo_name': base.HG_REPO}) gr = RepoGroupModel().create(group_name=u'group_test', group_description=u'desc', parent=None, - owner=TEST_USER_ADMIN_LOGIN) + owner=base.TEST_USER_ADMIN_LOGIN) with pytest.raises(formencode.Invalid): validator.to_python({'repo_name': gr.group_name}) @@ -163,7 +163,7 @@ # this uses ValidRepoName validator assert True - @parametrize('name,expected', [ + @base.parametrize('name,expected', [ ('test', 'test'), ('lolz!', 'lolz'), (' aavv', 'aavv'), ('ala ma kota', 'ala-ma-kota'), ('@nooo', 'nooo'), ('$!haha lolz !', 'haha-lolz'), ('$$$$$', ''), ('{}OK!', 'OK'), @@ -196,7 +196,7 @@ def test_ValidPath(self): validator = v.ValidPath() - assert TESTS_TMP_PATH == validator.to_python(TESTS_TMP_PATH) + assert base.TESTS_TMP_PATH == validator.to_python(base.TESTS_TMP_PATH) with pytest.raises(formencode.Invalid): validator.to_python('/no_such_dir') @@ -205,20 +205,20 @@ assert 'mail@python.org' == validator.to_python('MaiL@Python.org') - email = TEST_USER_REGULAR2_EMAIL + email = base.TEST_USER_REGULAR2_EMAIL with pytest.raises(formencode.Invalid): validator.to_python(email) def test_ValidSystemEmail(self): validator = v.ValidSystemEmail() - email = TEST_USER_REGULAR2_EMAIL + email = base.TEST_USER_REGULAR2_EMAIL assert email == validator.to_python(email) with pytest.raises(formencode.Invalid): validator.to_python('err') def test_LdapLibValidator(self): - if ldap_lib_installed: + if base.ldap_lib_installed: validator = v.LdapLibValidator() assert "DN" == validator.to_python('DN') else: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/other/test_vcs_operations.py --- a/kallithea/tests/other/test_vcs_operations.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/other/test_vcs_operations.py Thu Feb 06 01:19:23 2020 +0100 @@ -32,18 +32,19 @@ import re import tempfile import time -import urllib2 +import urllib.request from subprocess import PIPE, Popen from tempfile import _RandomNameSequence import pytest from kallithea import CONFIG +from kallithea.lib.utils2 import ascii_bytes, safe_str from kallithea.model.db import CacheInvalidation, Repository, Ui, User, UserIpMap, UserLog from kallithea.model.meta import Session from kallithea.model.ssh_key import SshKeyModel from kallithea.model.user import UserModel -from kallithea.tests.base import * +from kallithea.tests import base from kallithea.tests.fixture import Fixture @@ -64,12 +65,12 @@ class SshVcsTest(object): public_keys = { - TEST_USER_REGULAR_LOGIN: u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== kallithea@localhost', - TEST_USER_ADMIN_LOGIN: u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUq== kallithea@localhost', + base.TEST_USER_REGULAR_LOGIN: u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== kallithea@localhost', + base.TEST_USER_ADMIN_LOGIN: u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUq== kallithea@localhost', } @classmethod - def repo_url_param(cls, webserver, repo_name, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS, client_ip=IP_ADDR): + def repo_url_param(cls, webserver, repo_name, username=base.TEST_USER_ADMIN_LOGIN, password=base.TEST_USER_ADMIN_PASS, client_ip=base.IP_ADDR): user = User.get_by_username(username) if user.ssh_keys: ssh_key = user.ssh_keys[0] @@ -83,11 +84,11 @@ # Mixins for using Mercurial and Git class HgVcsTest(object): repo_type = 'hg' - repo_name = HG_REPO + repo_name = base.HG_REPO class GitVcsTest(object): repo_type = 'git' - repo_name = GIT_REPO + repo_name = base.GIT_REPO # Combine mixins to give the combinations we want to parameterize tests with class HgHttpVcsTest(HgVcsTest, HttpVcsTest): @@ -118,17 +119,17 @@ ssh_key.user_ssh_key_id) return "ssh://someuser@somehost/%s""" % repo_name -parametrize_vcs_test = parametrize('vt', [ +parametrize_vcs_test = base.parametrize('vt', [ HgHttpVcsTest, GitHttpVcsTest, HgSshVcsTest, GitSshVcsTest, ]) -parametrize_vcs_test_hg = parametrize('vt', [ +parametrize_vcs_test_hg = base.parametrize('vt', [ HgHttpVcsTest, HgSshVcsTest, ]) -parametrize_vcs_test_http = parametrize('vt', [ +parametrize_vcs_test_http = base.parametrize('vt', [ HgHttpVcsTest, GitHttpVcsTest, ]) @@ -162,11 +163,11 @@ print('stderr:', stderr) if not ignoreReturnCode: assert p.returncode == 0 - return stdout, stderr + return safe_str(stdout), safe_str(stderr) def _get_tmp_dir(prefix='vcs_operations-', suffix=''): - return tempfile.mkdtemp(dir=TESTS_TMP_PATH, prefix=prefix, suffix=suffix) + return tempfile.mkdtemp(dir=base.TESTS_TMP_PATH, prefix=prefix, suffix=suffix) def _add_files(vcs, dest_dir, files_no=3): @@ -177,7 +178,7 @@ :param vcs: :param dest_dir: """ - added_file = '%ssetup.py' % _RandomNameSequence().next() + added_file = '%ssetup.py' % next(_RandomNameSequence()) open(os.path.join(dest_dir, added_file), 'a').close() Command(dest_dir).execute(vcs, 'add', added_file) @@ -186,7 +187,7 @@ author_str = 'User <%s>' % email else: author_str = 'User ǝɯɐᴎ <%s>' % email - for i in xrange(files_no): + for i in range(files_no): cmd = """echo "added_line%s" >> %s""" % (i, added_file) Command(dest_dir).execute(cmd) if vcs == 'hg': @@ -242,7 +243,7 @@ @pytest.mark.usefixtures("test_context_fixture") -class TestVCSOperations(TestController): +class TestVCSOperations(base.TestController): @classmethod def setup_class(cls): @@ -262,16 +263,16 @@ @pytest.fixture(scope="module") def testfork(self): # create fork so the repo stays untouched - git_fork_name = u'%s_fork%s' % (GIT_REPO, _RandomNameSequence().next()) - fixture.create_fork(GIT_REPO, git_fork_name) - hg_fork_name = u'%s_fork%s' % (HG_REPO, _RandomNameSequence().next()) - fixture.create_fork(HG_REPO, hg_fork_name) + git_fork_name = u'%s_fork%s' % (base.GIT_REPO, next(_RandomNameSequence())) + fixture.create_fork(base.GIT_REPO, git_fork_name) + hg_fork_name = u'%s_fork%s' % (base.HG_REPO, next(_RandomNameSequence())) + fixture.create_fork(base.HG_REPO, hg_fork_name) return {'git': git_fork_name, 'hg': hg_fork_name} @parametrize_vcs_test def test_clone_repo_by_admin(self, webserver, vt): clone_url = vt.repo_url_param(webserver, vt.repo_name) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir()) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir()) if vt.repo_type == 'git': assert 'Cloning into' in stdout + stderr @@ -286,26 +287,26 @@ @parametrize_vcs_test_http def test_clone_wrong_credentials(self, webserver, vt): clone_url = vt.repo_url_param(webserver, vt.repo_name, password='bad!') - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) if vt.repo_type == 'git': assert 'fatal: Authentication failed' in stderr elif vt.repo_type == 'hg': assert 'abort: authorization failed' in stderr def test_clone_git_dir_as_hg(self, webserver): - clone_url = HgHttpVcsTest.repo_url_param(webserver, GIT_REPO) - stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) + clone_url = HgHttpVcsTest.repo_url_param(webserver, base.GIT_REPO) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) assert 'HTTP Error 404: Not Found' in stderr or "not a valid repository" in stdout and 'abort:' in stderr def test_clone_hg_repo_as_git(self, webserver): - clone_url = GitHttpVcsTest.repo_url_param(webserver, HG_REPO) - stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) + clone_url = GitHttpVcsTest.repo_url_param(webserver, base.HG_REPO) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) assert 'not found' in stderr @parametrize_vcs_test def test_clone_non_existing_path(self, webserver, vt): clone_url = vt.repo_url_param(webserver, 'trololo') - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) if vt.repo_type == 'git': assert 'not found' in stderr or 'abort: Access to %r denied' % 'trololo' in stderr elif vt.repo_type == 'hg': @@ -318,21 +319,21 @@ Session().commit() # Create an empty server repo using the API - repo_name = u'new_%s_%s' % (vt.repo_type, _RandomNameSequence().next()) - usr = User.get_by_username(TEST_USER_ADMIN_LOGIN) + repo_name = u'new_%s_%s' % (vt.repo_type, next(_RandomNameSequence())) + usr = User.get_by_username(base.TEST_USER_ADMIN_LOGIN) params = { "id": 7, "api_key": usr.api_key, "method": 'create_repo', "args": dict(repo_name=repo_name, - owner=TEST_USER_ADMIN_LOGIN, + owner=base.TEST_USER_ADMIN_LOGIN, repo_type=vt.repo_type), } - req = urllib2.Request( + req = urllib.request.Request( 'http://%s:%s/_admin/api' % webserver.server_address, - data=json.dumps(params), + data=ascii_bytes(json.dumps(params)), headers={'content-type': 'application/json'}) - response = urllib2.urlopen(req) + response = urllib.request.urlopen(req) result = json.loads(response.read()) # Expect something like: # {u'result': {u'msg': u'Created new repository `new_XXX`', u'task': None, u'success': True}, u'id': 7, u'error': None} @@ -341,7 +342,7 @@ # Create local clone of the empty server repo local_clone_dir = _get_tmp_dir() clone_url = vt.repo_url_param(webserver, repo_name) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, local_clone_dir) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, local_clone_dir) # Make 3 commits and push to the empty server repo. # The server repo doesn't have any other heads than the @@ -378,7 +379,7 @@ dest_dir = _get_tmp_dir() clone_url = vt.repo_url_param(webserver, vt.repo_name) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type]) stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, clone_url=clone_url) @@ -400,7 +401,7 @@ Session().commit() dest_dir = _get_tmp_dir() - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'init', dest_dir) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'init', dest_dir) clone_url = vt.repo_url_param(webserver, vt.repo_name) stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull', clone_url) @@ -413,6 +414,32 @@ action_parts = [ul.action for ul in UserLog.query().order_by(UserLog.user_log_id)] assert action_parts == [u'pull'] + # Test handling of URLs with extra '/' around repo_name + stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull', clone_url.replace('/' + vt.repo_name, '/./%s/' % vt.repo_name), ignoreReturnCode=True) + if issubclass(vt, HttpVcsTest): + if vt.repo_type == 'git': + # NOTE: when pulling from http://hostname/./vcs_test_git/ , the git client will normalize that and issue an HTTP request to /vcs_test_git/info/refs + assert 'Already up to date.' in stdout + else: + assert vt.repo_type == 'hg' + assert "abort: HTTP Error 404: Not Found" in stderr + else: + assert issubclass(vt, SshVcsTest) + if vt.repo_type == 'git': + assert "abort: Access to './%s' denied" % vt.repo_name in stderr + else: + assert "abort: Access to './%s' denied" % vt.repo_name in stdout + + stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull', clone_url.replace('/' + vt.repo_name, '/%s/' % vt.repo_name), ignoreReturnCode=True) + if vt.repo_type == 'git': + assert 'Already up to date.' in stdout + else: + assert vt.repo_type == 'hg' + assert "no changes found" in stdout + assert "denied" not in stderr + assert "denied" not in stdout + assert "404" not in stdout + @parametrize_vcs_test def test_push_invalidates_cache(self, webserver, testfork, vt): pre_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter(Repository.repo_name == testfork[vt.repo_type])] @@ -428,7 +455,7 @@ dest_dir = _get_tmp_dir() clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type]) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, files_no=1, clone_url=clone_url) @@ -446,7 +473,7 @@ def test_push_wrong_credentials(self, webserver, vt): dest_dir = _get_tmp_dir() clone_url = vt.repo_url_param(webserver, vt.repo_name) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) clone_url = webserver.repo_url(vt.repo_name, username='bad', password='name') stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, @@ -463,8 +490,8 @@ Session().commit() dest_dir = _get_tmp_dir() - clone_url = vt.repo_url_param(webserver, vt.repo_name, username=TEST_USER_REGULAR_LOGIN, password=TEST_USER_REGULAR_PASS) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) + clone_url = vt.repo_url_param(webserver, vt.repo_name, username=base.TEST_USER_REGULAR_LOGIN, password=base.TEST_USER_REGULAR_PASS) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, ignoreReturnCode=True, clone_url=clone_url) @@ -481,7 +508,7 @@ def test_push_back_to_wrong_url(self, webserver, vt): dest_dir = _get_tmp_dir() clone_url = vt.repo_url_param(webserver, vt.repo_name) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) stdout, stderr = _add_files_and_push( webserver, vt, dest_dir, clone_url='http://%s:%s/tmp' % ( @@ -498,12 +525,12 @@ user_model = UserModel() try: # Add IP constraint that excludes the test context: - user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') + user_model.add_extra_ip(base.TEST_USER_ADMIN_LOGIN, '10.10.10.10/32') Session().commit() # IP permissions are cached, need to wait for the cache in the server process to expire time.sleep(1.5) clone_url = vt.repo_url_param(webserver, vt.repo_name) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) if vt.repo_type == 'git': # The message apparently changed in Git 1.8.3, so match it loosely. assert re.search(r'\b403\b', stderr) or 'abort: User test_admin from 127.0.0.127 cannot be authorized' in stderr @@ -518,7 +545,7 @@ time.sleep(1.5) clone_url = vt.repo_url_param(webserver, vt.repo_name) - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir()) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir()) if vt.repo_type == 'git': assert 'Cloning into' in stdout + stderr @@ -537,9 +564,9 @@ Ui.create_or_update_hook('preoutgoing.testhook', 'python:kallithea.tests.fixture.failing_test_hook') Session().commit() # clone repo - clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type], username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS) + clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type], username=base.TEST_USER_ADMIN_LOGIN, password=base.TEST_USER_ADMIN_PASS) dest_dir = _get_tmp_dir() - stdout, stderr = Command(TESTS_TMP_PATH) \ + stdout, stderr = Command(base.TESTS_TMP_PATH) \ .execute(vt.repo_type, 'clone', clone_url, dest_dir, ignoreReturnCode=True) if vt.repo_type == 'hg': assert 'preoutgoing.testhook hook failed' in stdout @@ -552,9 +579,9 @@ Ui.create_or_update_hook('prechangegroup.testhook', 'python:kallithea.tests.fixture.failing_test_hook') Session().commit() # clone repo - clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type], username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS) + clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type], username=base.TEST_USER_ADMIN_LOGIN, password=base.TEST_USER_ADMIN_PASS) dest_dir = _get_tmp_dir() - stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir) stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, clone_url, ignoreReturnCode=True) @@ -595,19 +622,19 @@ def test_add_submodule_git(self, webserver, testfork): dest_dir = _get_tmp_dir() - clone_url = GitHttpVcsTest.repo_url_param(webserver, GIT_REPO) + clone_url = GitHttpVcsTest.repo_url_param(webserver, base.GIT_REPO) fork_url = GitHttpVcsTest.repo_url_param(webserver, testfork['git']) # add submodule - stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', fork_url, dest_dir) + stdout, stderr = Command(base.TESTS_TMP_PATH).execute('git clone', fork_url, dest_dir) stdout, stderr = Command(dest_dir).execute('git submodule add', clone_url, 'testsubmodule') - stdout, stderr = Command(dest_dir).execute('git commit -am "added testsubmodule pointing to', clone_url, '"', EMAIL=TEST_USER_ADMIN_EMAIL) + stdout, stderr = Command(dest_dir).execute('git commit -am "added testsubmodule pointing to', clone_url, '"', EMAIL=base.TEST_USER_ADMIN_EMAIL) stdout, stderr = Command(dest_dir).execute('git push', fork_url, 'master') # check for testsubmodule link in files page self.log_user() - response = self.app.get(url(controller='files', action='index', + response = self.app.get(base.url(controller='files', action='index', repo_name=testfork['git'], revision='tip', f_path='/')) @@ -617,7 +644,7 @@ response.mustcontain('testsubmodule @ ' % clone_url) # check that following a submodule link actually works - and redirects - response = self.app.get(url(controller='files', action='index', + response = self.app.get(base.url(controller='files', action='index', repo_name=testfork['git'], revision='tip', f_path='/testsubmodule'), diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/performance/test_vcs.py --- a/kallithea/tests/performance/test_vcs.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/performance/test_vcs.py Thu Feb 06 01:19:23 2020 +0100 @@ -15,11 +15,11 @@ import pytest from kallithea.model.db import Repository -from kallithea.tests.base import * +from kallithea.tests import base -@pytest.mark.skipif("not os.environ.has_key('TEST_PERFORMANCE')", reason="skipping performance tests, set TEST_PERFORMANCE in environment if desired") -class TestVCSPerformance(TestController): +@pytest.mark.skipif("'TEST_PERFORMANCE' not in os.environ", reason="skipping performance tests, set TEST_PERFORMANCE in environment if desired") +class TestVCSPerformance(base.TestController): def graphmod(self, repo): """ Simple test for running the graph_data function for profiling/testing performance. """ @@ -31,7 +31,7 @@ jsdata = graph_data(scm_inst, revs) def test_graphmod_hg(self, benchmark): - benchmark(self.graphmod, HG_REPO) + benchmark(self.graphmod, base.HG_REPO) def test_graphmod_git(self, benchmark): - benchmark(self.graphmod, GIT_REPO) + benchmark(self.graphmod, base.GIT_REPO) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/scripts/manual_test_concurrency.py --- a/kallithea/tests/scripts/manual_test_concurrency.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/scripts/manual_test_concurrency.py Thu Feb 06 01:19:23 2020 +0100 @@ -41,7 +41,6 @@ from kallithea.config.environment import load_environment from kallithea.lib.auth import get_crypt_password -from kallithea.lib.utils import setup_cache_regions from kallithea.model import meta from kallithea.model.base import init_model from kallithea.model.db import Repository, Ui, User @@ -52,8 +51,6 @@ conf = appconfig('config:development.ini', relative_to=rel_path) load_environment(conf.global_conf, conf.local_conf) -setup_cache_regions(conf) - USER = TEST_USER_ADMIN_LOGIN PASS = TEST_USER_ADMIN_PASS HOST = 'server.local' @@ -205,7 +202,7 @@ backend = 'hg' if METHOD == 'pull': - seq = tempfile._RandomNameSequence().next() + seq = next(tempfile._RandomNameSequence()) test_clone_with_credentials(repo=sys.argv[1], method='clone', backend=backend) s = time.time() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/scripts/manual_test_crawler.py --- a/kallithea/tests/scripts/manual_test_crawler.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/scripts/manual_test_crawler.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- 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 @@ -32,13 +32,13 @@ from __future__ import print_function -import cookielib +import http.cookiejar import os import sys import tempfile import time -import urllib -import urllib2 +import urllib.parse +import urllib.request from os.path import dirname from kallithea.lib import vcs @@ -72,18 +72,18 @@ ] -cj = cookielib.FileCookieJar(os.path.join(tempfile.gettempdir(), 'rc_test_cookie.txt')) -o = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) +cj = http.cookiejar.FileCookieJar(os.path.join(tempfile.gettempdir(), 'rc_test_cookie.txt')) +o = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj)) o.addheaders = [ ('User-agent', 'kallithea-crawler'), ('Accept-Language', 'en - us, en;q = 0.5') ] -urllib2.install_opener(o) +urllib.request.install_opener(o) def _get_repo(proj): - if isinstance(proj, basestring): + if isinstance(proj, str): repo = vcs.get_repo(os.path.join(PROJECT_PATH, proj)) proj = proj else: @@ -101,7 +101,7 @@ page = '/'.join((proj, 'changelog',)) - full_uri = (BASE_URI % page) + '?' + urllib.urlencode({'page': i}) + full_uri = (BASE_URI % page) + '?' + urllib.parse.urlencode({'page': i}) s = time.time() f = o.open(full_uri) @@ -130,13 +130,13 @@ break full_uri = (BASE_URI % raw_cs) - print('%s visiting %s\%s' % (cnt, full_uri, i)) + print('%s visiting %s/%s' % (cnt, full_uri, i)) s = time.time() f = o.open(full_uri) size = len(f.read()) e = time.time() - s total_time += e - print('%s visited %s\%s size:%s req:%s ms' % (cnt, full_uri, i, size, e)) + print('%s visited %s/%s size:%s req:%s ms' % (cnt, full_uri, i, size, e)) print('total_time', total_time) print('average on req', total_time / float(cnt)) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/base.py --- a/kallithea/tests/vcs/base.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/base.py Thu Feb 06 01:19:23 2020 +0100 @@ -79,8 +79,8 @@ for node in commit.get('removed', []): cls.imc.remove(FileNode(node.path)) - cls.tip = cls.imc.commit(message=unicode(commit['message']), - author=unicode(commit['author']), + cls.tip = cls.imc.commit(message=commit['message'], + author=commit['author'], date=commit['date']) @pytest.fixture(autouse=True) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_archives.py --- a/kallithea/tests/vcs/test_archives.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_archives.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,6 +1,6 @@ import datetime +import io import os -import StringIO import tarfile import tempfile import zipfile @@ -18,7 +18,7 @@ @classmethod def _get_commits(cls): start_date = datetime.datetime(2010, 1, 1, 20) - for x in xrange(5): + for x in range(5): yield { 'message': 'Commit %d' % x, 'author': 'Joe Doe ', @@ -35,11 +35,10 @@ self.tip.fill_archive(stream=f, kind='zip', prefix='repo') out = zipfile.ZipFile(path) - for x in xrange(5): + for x in range(5): node_path = '%d/file_%d.txt' % (x, x) - decompressed = StringIO.StringIO() - decompressed.write(out.read('repo/' + node_path)) - assert decompressed.getvalue() == self.tip.get_node(node_path).content + decompressed = out.read('repo/' + node_path) + assert decompressed == self.tip.get_node(node_path).content def test_archive_tgz(self): path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_tgz-')[1] @@ -50,9 +49,9 @@ outfile = tarfile.open(path, 'r|gz') outfile.extractall(outdir) - for x in xrange(5): + for x in range(5): node_path = '%d/file_%d.txt' % (x, x) - assert open(os.path.join(outdir, 'repo/' + node_path)).read() == self.tip.get_node(node_path).content + assert open(os.path.join(outdir, 'repo/' + node_path), 'rb').read() == self.tip.get_node(node_path).content def test_archive_tbz2(self): path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_tbz2-')[1] @@ -63,15 +62,15 @@ outfile = tarfile.open(path, 'r|bz2') outfile.extractall(outdir) - for x in xrange(5): + for x in range(5): node_path = '%d/file_%d.txt' % (x, x) - assert open(os.path.join(outdir, 'repo/' + node_path)).read() == self.tip.get_node(node_path).content + assert open(os.path.join(outdir, 'repo/' + node_path), 'rb').read() == self.tip.get_node(node_path).content def test_archive_default_stream(self): tmppath = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_default_stream-')[1] with open(tmppath, 'wb') as stream: self.tip.fill_archive(stream=stream) - mystream = StringIO.StringIO() + mystream = io.BytesIO() self.tip.fill_archive(stream=mystream) mystream.seek(0) with open(tmppath, 'rb') as f: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_changesets.py --- a/kallithea/tests/vcs/test_changesets.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_changesets.py Thu Feb 06 01:19:23 2020 +0100 @@ -15,7 +15,6 @@ def test_as_dict(self): changeset = BaseChangeset() - changeset.id = 'ID' changeset.raw_id = 'RAW_ID' changeset.short_id = 'SHORT_ID' changeset.revision = 1009 @@ -26,7 +25,6 @@ changeset.changed = [] changeset.removed = [] assert changeset.as_dict() == { - 'id': 'ID', 'raw_id': 'RAW_ID', 'short_id': 'SHORT_ID', 'revision': 1009, @@ -47,7 +45,7 @@ @classmethod def _get_commits(cls): start_date = datetime.datetime(2010, 1, 1, 20) - for x in xrange(5): + for x in range(5): yield { 'message': 'Commit %d' % x, 'author': 'Joe Doe ', @@ -69,7 +67,7 @@ assert foobar_tip.branch == 'foobar' assert foobar_tip.branches == ['foobar'] # 'foobar' should be the only branch that contains the new commit - branch_tips = self.repo.branches.values() + branch_tips = list(self.repo.branches.values()) assert branch_tips.count(str(foobar_tip.raw_id)) == 1 def test_new_head_in_default_branch(self): @@ -121,11 +119,11 @@ assert doc_changeset not in default_branch_changesets def test_get_changeset_by_branch(self): - for branch, sha in self.repo.branches.iteritems(): + for branch, sha in self.repo.branches.items(): assert sha == self.repo.get_changeset(branch).raw_id def test_get_changeset_by_tag(self): - for tag, sha in self.repo.tags.iteritems(): + for tag, sha in self.repo.tags.items(): assert sha == self.repo.get_changeset(tag).raw_id def test_get_changeset_parents(self): @@ -145,7 +143,7 @@ @classmethod def _get_commits(cls): start_date = datetime.datetime(2010, 1, 1, 20) - for x in xrange(5): + for x in range(5): yield { 'message': u'Commit %d' % x, 'author': u'Joe Doe ', @@ -240,7 +238,7 @@ def test_get_filenodes_generator(self): tip = self.repo.get_changeset() filepaths = [node.path for node in tip.get_filenodes_generator()] - assert filepaths == ['file_%d.txt' % x for x in xrange(5)] + assert filepaths == ['file_%d.txt' % x for x in range(5)] def test_size(self): tip = self.repo.get_changeset() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_filenodes_unicode_path.py --- a/kallithea/tests/vcs/test_filenodes_unicode_path.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_filenodes_unicode_path.py Thu Feb 06 01:19:23 2020 +0100 @@ -8,29 +8,22 @@ class FileNodeUnicodePathTestsMixin(_BackendTestMixin): - fname = 'ąśðąęłąć.txt' - ufname = (fname).decode('utf-8') + fname = u'ąśðąęłąć.txt' @classmethod def _get_commits(cls): - cls.nodes = [ - FileNode(cls.fname, content='Foobar'), - ] - - commits = [ + return [ { 'message': 'Initial commit', 'author': 'Joe Doe ', 'date': datetime.datetime(2010, 1, 1, 20), - 'added': cls.nodes, + 'added': [FileNode(cls.fname, content='Foobar')], }, ] - return commits def test_filenode_path(self): node = self.tip.get_node(self.fname) - unode = self.tip.get_node(self.ufname) - assert node == unode + assert node.path == self.fname class TestGitFileNodeUnicodePath(FileNodeUnicodePathTestsMixin): diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_getitem.py --- a/kallithea/tests/vcs/test_getitem.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_getitem.py Thu Feb 06 01:19:23 2020 +0100 @@ -9,7 +9,7 @@ @classmethod def _get_commits(cls): start_date = datetime.datetime(2010, 1, 1, 20) - for x in xrange(5): + for x in range(5): yield { 'message': 'Commit %d' % x, 'author': 'Joe Doe ', @@ -23,7 +23,7 @@ assert self.repo[-1] == self.repo.get_changeset() def test__getitem__returns_correct_items(self): - changesets = [self.repo[x] for x in xrange(len(self.repo.revisions))] + changesets = [self.repo[x] for x in range(len(self.repo.revisions))] assert changesets == list(self.repo.get_changesets()) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_getslice.py --- a/kallithea/tests/vcs/test_getslice.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_getslice.py Thu Feb 06 01:19:23 2020 +0100 @@ -9,7 +9,7 @@ @classmethod def _get_commits(cls): start_date = datetime.datetime(2010, 1, 1, 20) - for x in xrange(5): + for x in range(5): yield { 'message': 'Commit %d' % x, 'author': 'Joe Doe ', diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_git.py --- a/kallithea/tests/vcs/test_git.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_git.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,7 +1,6 @@ import datetime import os import sys -import urllib2 import mock import pytest @@ -31,8 +30,8 @@ GitRepository(wrong_repo_path) def test_git_cmd_injection(self): - repo_inject_path = TEST_GIT_REPO + '; echo "Cake";' - with pytest.raises(urllib2.URLError): + repo_inject_path = 'file:/%s; echo "Cake";' % TEST_GIT_REPO + with pytest.raises(RepositoryError): # Should fail because URL will contain the parts after ; too GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True) @@ -229,7 +228,7 @@ def test_changeset10(self): chset10 = self.repo.get_changeset(self.repo.revisions[9]) - readme = """=== + readme = b"""=== VCS === @@ -343,7 +342,7 @@ start = offset end = limit and offset + limit or None sliced = list(self.repo[start:end]) - pytest.failUnlessEqual(result, sliced, + pytest.assertEqual(result, sliced, msg="Comparison failed for limit=%s, offset=%s" "(get_changeset returned: %s and sliced: %s" % (limit, offset, result, sliced)) @@ -588,19 +587,19 @@ 'vcs/nodes.py'] assert set(changed) == set([f.path for f in chset.changed]) - def test_commit_message_is_unicode(self): + def test_commit_message_is_str(self): for cs in self.repo: - assert type(cs.message) == unicode + assert isinstance(cs.message, str) - def test_changeset_author_is_unicode(self): + def test_changeset_author_is_str(self): for cs in self.repo: - assert type(cs.author) == unicode + assert isinstance(cs.author, str) - def test_repo_files_content_is_unicode(self): + def test_repo_files_content_is_bytes(self): changeset = self.repo.get_changeset() for node in changeset.get_node('/'): if node.is_file(): - assert type(node.content) == unicode + assert isinstance(node.content, bytes) def test_wrong_path(self): # There is 'setup.py' in the root dir but not there: @@ -620,30 +619,6 @@ assert 'marcink none@none' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_name -class TestGitSpecific(): - - def test_error_is_raised_for_added_if_diff_name_status_is_wrong(self): - repo = mock.MagicMock() - changeset = GitChangeset(repo, 'foobar') - changeset._diff_name_status = 'foobar' - with pytest.raises(VCSError): - changeset.added - - def test_error_is_raised_for_changed_if_diff_name_status_is_wrong(self): - repo = mock.MagicMock() - changeset = GitChangeset(repo, 'foobar') - changeset._diff_name_status = 'foobar' - with pytest.raises(VCSError): - changeset.added - - def test_error_is_raised_for_removed_if_diff_name_status_is_wrong(self): - repo = mock.MagicMock() - changeset = GitChangeset(repo, 'foobar') - changeset._diff_name_status = 'foobar' - with pytest.raises(VCSError): - changeset.added - - class TestGitSpecificWithRepo(_BackendTestMixin): backend_alias = 'git' @@ -657,7 +632,7 @@ 'added': [ FileNode('foobar/static/js/admin/base.js', content='base'), FileNode('foobar/static/admin', content='admin', - mode=0120000), # this is a link + mode=0o120000), # this is a link FileNode('foo', content='foo'), ], }, @@ -673,11 +648,11 @@ def test_paths_slow_traversing(self): cs = self.repo.get_changeset() - assert cs.get_node('foobar').get_node('static').get_node('js').get_node('admin').get_node('base.js').content == 'base' + assert cs.get_node('foobar').get_node('static').get_node('js').get_node('admin').get_node('base.js').content == b'base' def test_paths_fast_traversing(self): cs = self.repo.get_changeset() - assert cs.get_node('foobar/static/js/admin/base.js').content == 'base' + assert cs.get_node('foobar/static/js/admin/base.js').content == b'base' def test_workdir_get_branch(self): self.repo.run_git_command(['checkout', '-b', 'production']) @@ -689,65 +664,65 @@ assert self.repo.workdir.get_branch() == 'master' def test_get_diff_runs_git_command_with_hashes(self): - self.repo.run_git_command = mock.Mock(return_value=['', '']) + self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) self.repo.get_diff(0, 1) - self.repo.run_git_command.assert_called_once_with( + self.repo._run_git_command.assert_called_once_with( ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', - self.repo._get_revision(0), self.repo._get_revision(1)]) + self.repo._get_revision(0), self.repo._get_revision(1)], cwd=self.repo.path) def test_get_diff_runs_git_command_with_str_hashes(self): - self.repo.run_git_command = mock.Mock(return_value=['', '']) + self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) self.repo.get_diff(self.repo.EMPTY_CHANGESET, 1) - self.repo.run_git_command.assert_called_once_with( + self.repo._run_git_command.assert_called_once_with( ['show', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', - self.repo._get_revision(1)]) + self.repo._get_revision(1)], cwd=self.repo.path) def test_get_diff_runs_git_command_with_path_if_its_given(self): - self.repo.run_git_command = mock.Mock(return_value=['', '']) + self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) self.repo.get_diff(0, 1, 'foo') - self.repo.run_git_command.assert_called_once_with( + self.repo._run_git_command.assert_called_once_with( ['diff', '-U3', '--full-index', '--binary', '-p', '-M', '--abbrev=40', - self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo']) + self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) def test_get_diff_does_not_sanitize_valid_context(self): almost_overflowed_long_int = 2**31-1 - self.repo.run_git_command = mock.Mock(return_value=['', '']) + self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) self.repo.get_diff(0, 1, 'foo', context=almost_overflowed_long_int) - self.repo.run_git_command.assert_called_once_with( + self.repo._run_git_command.assert_called_once_with( ['diff', '-U' + str(almost_overflowed_long_int), '--full-index', '--binary', '-p', '-M', '--abbrev=40', - self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo']) + self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) def test_get_diff_sanitizes_overflowing_context(self): overflowed_long_int = 2**31 sanitized_overflowed_long_int = overflowed_long_int-1 - self.repo.run_git_command = mock.Mock(return_value=['', '']) + self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) self.repo.get_diff(0, 1, 'foo', context=overflowed_long_int) - self.repo.run_git_command.assert_called_once_with( + self.repo._run_git_command.assert_called_once_with( ['diff', '-U' + str(sanitized_overflowed_long_int), '--full-index', '--binary', '-p', '-M', '--abbrev=40', - self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo']) + self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) def test_get_diff_does_not_sanitize_zero_context(self): zero_context = 0 - self.repo.run_git_command = mock.Mock(return_value=['', '']) + self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) self.repo.get_diff(0, 1, 'foo', context=zero_context) - self.repo.run_git_command.assert_called_once_with( + self.repo._run_git_command.assert_called_once_with( ['diff', '-U' + str(zero_context), '--full-index', '--binary', '-p', '-M', '--abbrev=40', - self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo']) + self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) def test_get_diff_sanitizes_negative_context(self): negative_context = -10 - self.repo.run_git_command = mock.Mock(return_value=['', '']) + self.repo._run_git_command = mock.Mock(return_value=(b'', b'')) self.repo.get_diff(0, 1, 'foo', context=negative_context) - self.repo.run_git_command.assert_called_once_with( + self.repo._run_git_command.assert_called_once_with( ['diff', '-U0', '--full-index', '--binary', '-p', '-M', '--abbrev=40', - self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo']) + self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'], cwd=self.repo.path) class TestGitRegression(_BackendTestMixin): @@ -804,22 +779,24 @@ self.repo = GitRepository(self.repo_directory, create=True) # Create a dictionary where keys are hook names, and values are paths to - # them. Deduplicates code in tests a bit. - self.hook_directory = self.repo.get_hook_location() - self.kallithea_hooks = dict((h, os.path.join(self.hook_directory, h)) for h in ("pre-receive", "post-receive")) + # them in the non-bare repo. Deduplicates code in tests a bit. + self.kallithea_hooks = { + "pre-receive": os.path.join(self.repo.path, '.git', 'hooks', "pre-receive"), + "post-receive": os.path.join(self.repo.path, '.git', 'hooks', "post-receive"), + } def test_hooks_created_if_missing(self): """ Tests if hooks are installed in repository if they are missing. """ - for hook, hook_path in self.kallithea_hooks.iteritems(): + for hook, hook_path in self.kallithea_hooks.items(): if os.path.exists(hook_path): os.remove(hook_path) ScmModel().install_git_hooks(repo=self.repo) - for hook, hook_path in self.kallithea_hooks.iteritems(): + for hook, hook_path in self.kallithea_hooks.items(): assert os.path.exists(hook_path) def test_kallithea_hooks_updated(self): @@ -827,13 +804,13 @@ Tests if hooks are updated if they are Kallithea hooks already. """ - for hook, hook_path in self.kallithea_hooks.iteritems(): + for hook, hook_path in self.kallithea_hooks.items(): with open(hook_path, "w") as f: f.write("KALLITHEA_HOOK_VER=0.0.0\nJUST_BOGUS") ScmModel().install_git_hooks(repo=self.repo) - for hook, hook_path in self.kallithea_hooks.iteritems(): + for hook, hook_path in self.kallithea_hooks.items(): with open(hook_path) as f: assert "JUST_BOGUS" not in f.read() @@ -842,13 +819,13 @@ Tests if hooks are left untouched if they are not Kallithea hooks. """ - for hook, hook_path in self.kallithea_hooks.iteritems(): + for hook, hook_path in self.kallithea_hooks.items(): with open(hook_path, "w") as f: f.write("#!/bin/bash\n#CUSTOM_HOOK") ScmModel().install_git_hooks(repo=self.repo) - for hook, hook_path in self.kallithea_hooks.iteritems(): + for hook, hook_path in self.kallithea_hooks.items(): with open(hook_path) as f: assert "CUSTOM_HOOK" in f.read() @@ -857,12 +834,12 @@ Tests if hooks are forcefully updated even though they are custom hooks. """ - for hook, hook_path in self.kallithea_hooks.iteritems(): + for hook, hook_path in self.kallithea_hooks.items(): with open(hook_path, "w") as f: f.write("#!/bin/bash\n#CUSTOM_HOOK") ScmModel().install_git_hooks(repo=self.repo, force_create=True) - for hook, hook_path in self.kallithea_hooks.iteritems(): + for hook, hook_path in self.kallithea_hooks.items(): with open(hook_path) as f: assert "KALLITHEA_HOOK_VER" in f.read() diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_hg.py --- a/kallithea/tests/vcs/test_hg.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_hg.py Thu Feb 06 01:19:23 2020 +0100 @@ -3,7 +3,6 @@ import mock import pytest -from kallithea.lib.utils2 import safe_str from kallithea.lib.vcs.backends.hg import MercurialChangeset, MercurialRepository from kallithea.lib.vcs.exceptions import NodeDoesNotExistError, RepositoryError, VCSError from kallithea.lib.vcs.nodes import NodeKind, NodeState @@ -19,7 +18,7 @@ % TEST_HG_REPO_CLONE) def setup_method(self): - self.repo = MercurialRepository(safe_str(TEST_HG_REPO)) + self.repo = MercurialRepository(TEST_HG_REPO) def test_wrong_repo_path(self): wrong_repo_path = os.path.join(TESTS_TMP_PATH, 'errorrepo') @@ -32,7 +31,7 @@ def test_repo_clone(self): self.__check_for_existing_repo() - repo = MercurialRepository(safe_str(TEST_HG_REPO)) + repo = MercurialRepository(TEST_HG_REPO) repo_clone = MercurialRepository(TEST_HG_REPO_CLONE, src_url=TEST_HG_REPO, update_after_clone=True) assert len(repo.revisions) == len(repo_clone.revisions) @@ -42,7 +41,7 @@ assert raw_id == repo_clone.get_changeset(raw_id).raw_id def test_repo_clone_with_update(self): - repo = MercurialRepository(safe_str(TEST_HG_REPO)) + repo = MercurialRepository(TEST_HG_REPO) repo_clone = MercurialRepository(TEST_HG_REPO_CLONE + '_w_update', src_url=TEST_HG_REPO, update_after_clone=True) assert len(repo.revisions) == len(repo_clone.revisions) @@ -55,7 +54,7 @@ ) def test_repo_clone_without_update(self): - repo = MercurialRepository(safe_str(TEST_HG_REPO)) + repo = MercurialRepository(TEST_HG_REPO) repo_clone = MercurialRepository(TEST_HG_REPO_CLONE + '_wo_update', src_url=TEST_HG_REPO, update_after_clone=False) assert len(repo.revisions) == len(repo_clone.revisions) @@ -219,7 +218,7 @@ def test_changeset10(self): chset10 = self.repo.get_changeset(10) - readme = """=== + readme = b"""=== VCS === @@ -235,7 +234,7 @@ assert node.kind == NodeKind.FILE assert node.content == readme - @mock.patch('kallithea.lib.vcs.backends.hg.repository.diffopts') + @mock.patch('mercurial.mdiff.diffopts') def test_get_diff_does_not_sanitize_zero_context(self, mock_diffopts): zero_context = 0 @@ -243,7 +242,7 @@ mock_diffopts.assert_called_once_with(git=True, showfunc=True, ignorews=False, context=zero_context) - @mock.patch('kallithea.lib.vcs.backends.hg.repository.diffopts') + @mock.patch('mercurial.mdiff.diffopts') def test_get_diff_sanitizes_negative_context(self, mock_diffopts): negative_context = -10 zero_context = 0 @@ -256,7 +255,7 @@ class TestMercurialChangeset(object): def setup_method(self): - self.repo = MercurialRepository(safe_str(TEST_HG_REPO)) + self.repo = MercurialRepository(TEST_HG_REPO) def _test_equality(self, changeset): revision = changeset.revision @@ -444,20 +443,20 @@ # added: 20 # removed: 1 changed = set(['.hgignore' - , 'README.rst' , 'docs/conf.py' , 'docs/index.rst' , 'setup.py' - , 'tests/test_hg.py' , 'tests/test_nodes.py' , 'vcs/__init__.py' - , 'vcs/backends/__init__.py' , 'vcs/backends/base.py' - , 'vcs/backends/hg.py' , 'vcs/nodes.py' , 'vcs/utils/__init__.py']) + , 'README.rst', 'docs/conf.py', 'docs/index.rst', 'setup.py' + , 'tests/test_hg.py', 'tests/test_nodes.py', 'vcs/__init__.py' + , 'vcs/backends/__init__.py', 'vcs/backends/base.py' + , 'vcs/backends/hg.py', 'vcs/nodes.py', 'vcs/utils/__init__.py']) added = set(['docs/api/backends/hg.rst' - , 'docs/api/backends/index.rst' , 'docs/api/index.rst' - , 'docs/api/nodes.rst' , 'docs/api/web/index.rst' - , 'docs/api/web/simplevcs.rst' , 'docs/installation.rst' - , 'docs/quickstart.rst' , 'setup.cfg' , 'vcs/utils/baseui_config.py' - , 'vcs/utils/web.py' , 'vcs/web/__init__.py' , 'vcs/web/exceptions.py' - , 'vcs/web/simplevcs/__init__.py' , 'vcs/web/simplevcs/exceptions.py' - , 'vcs/web/simplevcs/middleware.py' , 'vcs/web/simplevcs/models.py' - , 'vcs/web/simplevcs/settings.py' , 'vcs/web/simplevcs/utils.py' + , 'docs/api/backends/index.rst', 'docs/api/index.rst' + , 'docs/api/nodes.rst', 'docs/api/web/index.rst' + , 'docs/api/web/simplevcs.rst', 'docs/installation.rst' + , 'docs/quickstart.rst', 'setup.cfg', 'vcs/utils/baseui_config.py' + , 'vcs/utils/web.py', 'vcs/web/__init__.py', 'vcs/web/exceptions.py' + , 'vcs/web/simplevcs/__init__.py', 'vcs/web/simplevcs/exceptions.py' + , 'vcs/web/simplevcs/middleware.py', 'vcs/web/simplevcs/models.py' + , 'vcs/web/simplevcs/settings.py', 'vcs/web/simplevcs/utils.py' , 'vcs/web/simplevcs/views.py']) removed = set(['docs/api.rst']) @@ -536,19 +535,19 @@ # but it would be one of ``removed`` (changeset's attribute) assert path in [rf.path for rf in chset.removed] - def test_commit_message_is_unicode(self): + def test_commit_message_is_str(self): for cm in self.repo: - assert type(cm.message) == unicode + assert isinstance(cm.message, str) - def test_changeset_author_is_unicode(self): + def test_changeset_author_is_str(self): for cm in self.repo: - assert type(cm.author) == unicode + assert isinstance(cm.author, str) - def test_repo_files_content_is_unicode(self): + def test_repo_files_content_is_bytes(self): test_changeset = self.repo.get_changeset(100) for node in test_changeset.get_node('/'): if node.is_file(): - assert type(node.content) == unicode + assert isinstance(node.content, bytes) def test_wrong_path(self): # There is 'setup.py' in the root dir but not there: diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_inmemchangesets.py --- a/kallithea/tests/vcs/test_inmemchangesets.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_inmemchangesets.py Thu Feb 06 01:19:23 2020 +0100 @@ -7,11 +7,9 @@ import pytest -from kallithea.lib import vcs from kallithea.lib.vcs.exceptions import ( EmptyRepositoryError, NodeAlreadyAddedError, NodeAlreadyChangedError, NodeAlreadyExistsError, NodeAlreadyRemovedError, NodeDoesNotExistError, NodeNotChangedError) from kallithea.lib.vcs.nodes import DirNode, FileNode -from kallithea.lib.vcs.utils import safe_unicode from kallithea.tests.vcs.base import _BackendTestMixin @@ -39,7 +37,7 @@ for node in to_add: self.imc.add(node) message = u'Added: %s' % ', '.join((node.path for node in self.nodes)) - author = unicode(self.__class__) + author = str(self.__class__) changeset = self.imc.commit(message=message, author=author) newtip = self.repo.get_changeset() @@ -61,7 +59,7 @@ for node in self.nodes] self.imc.add(*to_add) message = u'Added: %s' % ', '.join((node.path for node in self.nodes)) - author = unicode(self.__class__) + author = str(self.__class__) changeset = self.imc.commit(message=message, author=author) newtip = self.repo.get_changeset() @@ -83,8 +81,8 @@ changeset = self.imc.commit(u'Initial', u'joe.doe@example.com') assert isinstance(changeset.get_node('foo'), DirNode) assert isinstance(changeset.get_node('foo/bar'), DirNode) - assert changeset.get_node('foo/bar/image.png').content == '\0' - assert changeset.get_node('foo/README.txt').content == 'readme!' + assert changeset.get_node('foo/bar/image.png').content == b'\0' + assert changeset.get_node('foo/README.txt').content == b'readme!' # commit some more files again to_add = [ @@ -96,11 +94,11 @@ ] self.imc.add(*to_add) changeset = self.imc.commit(u'Another', u'joe.doe@example.com') - changeset.get_node('foo/bar/foobaz/bar').content == 'foo' - changeset.get_node('foo/bar/another/bar').content == 'foo' - changeset.get_node('foo/baz.txt').content == 'foo' - changeset.get_node('foobar/foobaz/file').content == 'foo' - changeset.get_node('foobar/barbaz').content == 'foo' + changeset.get_node('foo/bar/foobaz/bar').content == b'foo' + changeset.get_node('foo/bar/another/bar').content == b'foo' + changeset.get_node('foo/baz.txt').content == b'foo' + changeset.get_node('foobar/foobaz/file').content == b'foo' + changeset.get_node('foobar/barbaz').content == b'foo' def test_add_non_ascii_files(self): rev_count = len(self.repo.revisions) @@ -111,7 +109,7 @@ for node in to_add: self.imc.add(node) message = u'Added: %s' % ', '.join((node.path for node in self.nodes)) - author = unicode(self.__class__) + author = str(self.__class__) changeset = self.imc.commit(message=message, author=author) newtip = self.repo.get_changeset() @@ -136,7 +134,7 @@ def test_check_integrity_raise_already_exist(self): node = FileNode('foobar', content='baz') self.imc.add(node) - self.imc.commit(message=u'Added foobar', author=unicode(self)) + self.imc.commit(message=u'Added foobar', author=str(self)) self.imc.add(node) with pytest.raises(NodeAlreadyExistsError): self.imc.commit(message='new message', @@ -154,8 +152,8 @@ newtip = self.repo.get_changeset() assert tip != newtip - assert tip.id != newtip.id - assert newtip.get_node('foo/bar/baz').content == 'My **changed** content' + assert tip.raw_id != newtip.raw_id + assert newtip.get_node('foo/bar/baz').content == b'My **changed** content' def test_change_non_ascii(self): to_add = [ @@ -170,20 +168,18 @@ # Change node's content node = FileNode('żółwik/zwierzątko', content='My **changed** content') self.imc.change(node) - self.imc.commit(u'Changed %s' % safe_unicode(node.path), - u'joe.doe@example.com') + self.imc.commit(u'Changed %s' % node.path, u'joe.doe@example.com') node = FileNode(u'żółwik/zwierzątko_uni', content=u'My **changed** content') self.imc.change(node) - self.imc.commit(u'Changed %s' % safe_unicode(node.path), - u'joe.doe@example.com') + self.imc.commit(u'Changed %s' % node.path, u'joe.doe@example.com') newtip = self.repo.get_changeset() assert tip != newtip - assert tip.id != newtip.id + assert tip.raw_id != newtip.raw_id - assert newtip.get_node('żółwik/zwierzątko').content == 'My **changed** content' - assert newtip.get_node('żółwik/zwierzątko_uni').content == 'My **changed** content' + assert newtip.get_node('żółwik/zwierzątko').content == b'My **changed** content' + assert newtip.get_node('żółwik/zwierzątko_uni').content == b'My **changed** content' def test_change_raise_empty_repository(self): node = FileNode('foobar') @@ -193,7 +189,7 @@ def test_check_integrity_change_raise_node_does_not_exist(self): node = FileNode('foobar', content='baz') self.imc.add(node) - self.imc.commit(message=u'Added foobar', author=unicode(self)) + self.imc.commit(message=u'Added foobar', author=str(self)) node = FileNode('not-foobar', content='') self.imc.change(node) with pytest.raises(NodeDoesNotExistError): @@ -202,7 +198,7 @@ def test_change_raise_node_already_changed(self): node = FileNode('foobar', content='baz') self.imc.add(node) - self.imc.commit(message=u'Added foobar', author=unicode(self)) + self.imc.commit(message=u'Added foobar', author=str(self)) node = FileNode('foobar', content='more baz') self.imc.change(node) with pytest.raises(NodeAlreadyChangedError): @@ -216,13 +212,13 @@ with pytest.raises(NodeNotChangedError): self.imc.commit( message=u'Trying to mark node as changed without touching it', - author=unicode(self) + author=str(self), ) def test_change_raise_node_already_removed(self): node = FileNode('foobar', content='baz') self.imc.add(node) - self.imc.commit(message=u'Added foobar', author=unicode(self)) + self.imc.commit(message=u'Added foobar', author=str(self)) self.imc.remove(FileNode('foobar')) with pytest.raises(NodeAlreadyRemovedError): self.imc.change(node) @@ -234,11 +230,11 @@ node = self.nodes[0] assert node.content == tip.get_node(node.path).content self.imc.remove(node) - self.imc.commit(message=u'Removed %s' % node.path, author=unicode(self)) + self.imc.commit(message=u'Removed %s' % node.path, author=str(self)) newtip = self.repo.get_changeset() assert tip != newtip - assert tip.id != newtip.id + assert tip.raw_id != newtip.raw_id with pytest.raises(NodeDoesNotExistError): newtip.get_node(node.path) @@ -257,7 +253,7 @@ with pytest.raises(NodeDoesNotExistError): self.imc.commit( message='Trying to remove node at empty repository', - author=str(self) + author=str(self), ) def test_check_integrity_remove_raise_node_does_not_exist(self): @@ -268,7 +264,7 @@ with pytest.raises(NodeDoesNotExistError): self.imc.commit( message=u'Trying to remove not existing node', - author=unicode(self) + author=str(self), ) def test_remove_raise_node_already_removed(self): @@ -301,7 +297,7 @@ def test_multiple_commits(self): N = 3 # number of commits to perform last = None - for x in xrange(N): + for x in range(N): fname = 'file%s' % str(x).rjust(5, '0') content = 'foobar\n' * x node = FileNode(fname, content=content) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_nodes.py --- a/kallithea/tests/vcs/test_nodes.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_nodes.py Thu Feb 06 01:19:23 2020 +0100 @@ -144,13 +144,13 @@ assert not mode & stat.S_IXOTH def test_file_node_is_executable(self): - node = FileNode('foobar', 'empty... almost', mode=0100755) + node = FileNode('foobar', 'empty... almost', mode=0o100755) assert node.is_executable - node = FileNode('foobar', 'empty... almost', mode=0100500) + node = FileNode('foobar', 'empty... almost', mode=0o100500) assert node.is_executable - node = FileNode('foobar', 'empty... almost', mode=0100644) + node = FileNode('foobar', 'empty... almost', mode=0o100644) assert not node.is_executable def test_mimetype(self): @@ -158,10 +158,10 @@ tar_node = FileNode('test.tar.gz') my_node2 = FileNode('myfile2') - my_node2._content = 'foobar' + my_node2._content = b'foobar' my_node3 = FileNode('myfile3') - my_node3._content = '\0foobar' + my_node3._content = b'\0foobar' assert py_node.mimetype == mimetypes.guess_type(py_node.name)[0] assert py_node.get_mimetype() == mimetypes.guess_type(py_node.name) diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_repository.py --- a/kallithea/tests/vcs/test_repository.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_repository.py Thu Feb 06 01:19:23 2020 +0100 @@ -110,7 +110,7 @@ def test_initial_commit_diff(self): initial_rev = self.repo.revisions[0] - assert self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev) == '''diff --git a/foobar b/foobar + assert self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev) == br'''diff --git a/foobar b/foobar new file mode 100644 index 0000000000000000000000000000000000000000..f6ea0495187600e7b2288c8ac19c5886383a4632 --- /dev/null @@ -130,7 +130,7 @@ def test_second_changeset_diff(self): revs = self.repo.revisions - assert self.repo.get_diff(revs[0], revs[1]) == '''diff --git a/foobar b/foobar + assert self.repo.get_diff(revs[0], revs[1]) == br'''diff --git a/foobar b/foobar index f6ea0495187600e7b2288c8ac19c5886383a4632..389865bb681b358c9b102d79abd8d5f941e96551 100644 --- a/foobar +++ b/foobar @@ -151,7 +151,7 @@ def test_third_changeset_diff(self): revs = self.repo.revisions - assert self.repo.get_diff(revs[1], revs[2]) == '''diff --git a/foobar b/foobar + assert self.repo.get_diff(revs[1], revs[2]) == br'''diff --git a/foobar b/foobar deleted file mode 100644 index 389865bb681b358c9b102d79abd8d5f941e96551..0000000000000000000000000000000000000000 --- a/foobar @@ -173,7 +173,7 @@ def test_fourth_changeset_diff(self): revs = self.repo.revisions - assert self.repo.get_diff(revs[2], revs[3]) == '''diff --git a/README{ b/README{ + assert self.repo.get_diff(revs[2], revs[3]) == br'''diff --git a/README{ b/README{ new file mode 100644 index 0000000000000000000000000000000000000000..cdc0c1b5d234feedb37bbac19cd1b6442061102d --- /dev/null @@ -189,7 +189,7 @@ def test_initial_commit_diff(self): initial_rev = self.repo.revisions[0] - assert self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev) == '''diff --git a/foobar b/foobar + assert self.repo.get_diff(self.repo.EMPTY_CHANGESET, initial_rev) == br'''diff --git a/foobar b/foobar new file mode 100644 --- /dev/null +++ b/foobar @@ -207,7 +207,7 @@ def test_second_changeset_diff(self): revs = self.repo.revisions - assert self.repo.get_diff(revs[0], revs[1]) == '''diff --git a/foobar b/foobar + assert self.repo.get_diff(revs[0], revs[1]) == br'''diff --git a/foobar b/foobar --- a/foobar +++ b/foobar @@ -1,1 +1,1 @@ @@ -226,7 +226,7 @@ def test_third_changeset_diff(self): revs = self.repo.revisions - assert self.repo.get_diff(revs[1], revs[2]) == '''diff --git a/foobar b/foobar + assert self.repo.get_diff(revs[1], revs[2]) == br'''diff --git a/foobar b/foobar deleted file mode 100644 --- a/foobar +++ /dev/null @@ -246,7 +246,7 @@ def test_fourth_changeset_diff(self): revs = self.repo.revisions - assert self.repo.get_diff(revs[2], revs[3]) == '''diff --git a/README{ b/README{ + assert self.repo.get_diff(revs[2], revs[3]) == br'''diff --git a/README{ b/README{ new file mode 100644 --- /dev/null +++ b/README{ diff -r 460e7d2d1b38 -r 928bc1d8b279 kallithea/tests/vcs/test_vcs.py --- a/kallithea/tests/vcs/test_vcs.py Sun Jan 05 01:19:05 2020 +0100 +++ b/kallithea/tests/vcs/test_vcs.py Thu Feb 06 01:19:23 2020 +0100 @@ -3,7 +3,6 @@ import pytest -from kallithea.lib.utils2 import safe_str from kallithea.lib.vcs import VCSError, get_backend, get_repo from kallithea.lib.vcs.backends.hg import MercurialRepository from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_HG_REPO, TESTS_TMP_PATH @@ -22,14 +21,14 @@ alias = 'hg' path = TEST_HG_REPO backend = get_backend(alias) - repo = backend(safe_str(path)) + repo = backend(path) assert 'hg' == repo.alias def test_alias_detect_git(self): alias = 'git' path = TEST_GIT_REPO backend = get_backend(alias) - repo = backend(safe_str(path)) + repo = backend(path) assert 'git' == repo.alias def test_wrong_alias(self): @@ -41,28 +40,28 @@ alias = 'hg' path = TEST_HG_REPO backend = get_backend(alias) - repo = backend(safe_str(path)) + repo = backend(path) - assert repo.__class__ == get_repo(safe_str(path), alias).__class__ - assert repo.path == get_repo(safe_str(path), alias).path + assert repo.__class__ == get_repo(path, alias).__class__ + assert repo.path == get_repo(path, alias).path def test_get_repo_autoalias_hg(self): alias = 'hg' path = TEST_HG_REPO backend = get_backend(alias) - repo = backend(safe_str(path)) + repo = backend(path) - assert repo.__class__ == get_repo(safe_str(path)).__class__ - assert repo.path == get_repo(safe_str(path)).path + assert repo.__class__ == get_repo(path).__class__ + assert repo.path == get_repo(path).path def test_get_repo_autoalias_git(self): alias = 'git' path = TEST_GIT_REPO backend = get_backend(alias) - repo = backend(safe_str(path)) + repo = backend(path) - assert repo.__class__ == get_repo(safe_str(path)).__class__ - assert repo.path == get_repo(safe_str(path)).path + assert repo.__class__ == get_repo(path).__class__ + assert repo.path == get_repo(path).path def test_get_repo_err(self): blank_repo_path = os.path.join(TESTS_TMP_PATH, 'blank-error-repo') diff -r 460e7d2d1b38 -r 928bc1d8b279 scripts/docs-headings.py --- a/scripts/docs-headings.py Sun Jan 05 01:19:05 2020 +0100 +++ b/scripts/docs-headings.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 """ Consistent formatting of rst section titles @@ -35,6 +35,7 @@ def main(): filenames = subprocess.check_output(['hg', 'loc', 'set:**.rst+kallithea/i18n/how_to']).splitlines() for fn in filenames: + fn = fn.decode() print('processing %s' % fn) s = open(fn).read() diff -r 460e7d2d1b38 -r 928bc1d8b279 scripts/generate-ini.py --- a/scripts/generate-ini.py Sun Jan 05 01:19:05 2020 +0100 +++ b/scripts/generate-ini.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 """ Based on kallithea/lib/paster_commands/template.ini.mako, generate development.ini """ diff -r 460e7d2d1b38 -r 928bc1d8b279 scripts/logformat.py --- a/scripts/logformat.py Sun Jan 05 01:19:05 2020 +0100 +++ b/scripts/logformat.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 from __future__ import print_function diff -r 460e7d2d1b38 -r 928bc1d8b279 scripts/make-release --- a/scripts/make-release Sun Jan 05 01:19:05 2020 +0100 +++ b/scripts/make-release Thu Feb 06 01:19:23 2020 +0100 @@ -15,11 +15,11 @@ trap cleanup EXIT echo "Setting up a fresh virtualenv in $venv" -virtualenv -p python2 "$venv" +python3 -m venv "$venv" . "$venv/bin/activate" echo "Install/verify tools needed for building and uploading stuff" -pip install --upgrade -e . -r dev_requirements.txt twine +pip install --upgrade -e . -r dev_requirements.txt twine python-ldap python-pam echo "Cleanup and update copyrights ... and clean checkout" scripts/run-all-cleanup @@ -35,8 +35,8 @@ sed -e 's/[^ ]*[ ]*\([^ ]*\).*/\1/g' MANIFEST.in | xargs ls -lad echo "Build dist" -python2 setup.py compile_catalog -python2 setup.py sdist +python3 setup.py compile_catalog +python3 setup.py sdist echo "Verify VERSION from kallithea/__init__.py" namerel=$(cd dist && echo Kallithea-*.tar.gz) @@ -46,10 +46,10 @@ echo "Releasing Kallithea $version in directory $namerel" echo "Verify dist file content" -diff -u <((hg mani | grep -v '^\.hg') | LANG=C sort) <(tar tf dist/Kallithea-$version.tar.gz | sed "s|^$namerel/||" | grep . | grep -v '^kallithea/i18n/.*/LC_MESSAGES/kallithea.mo$\|^Kallithea.egg-info/\|^PKG-INFO$\|/$' | LANG=C sort) +diff -u <((hg mani | grep -v '^\.hg\|^kallithea/i18n/en/LC_MESSAGES/kallithea.mo$') | LANG=C sort) <(tar tf dist/Kallithea-$version.tar.gz | sed "s|^$namerel/||" | grep . | grep -v '^kallithea/i18n/.*/LC_MESSAGES/kallithea.mo$\|^Kallithea.egg-info/\|^PKG-INFO$\|/$' | LANG=C sort) echo "Verify docs build" -python2 setup.py build_sphinx # the results are not actually used, but we want to make sure it builds +python3 setup.py build_sphinx # the results are not actually used, but we want to make sure it builds echo "Shortlog for inclusion in the release announcement" scripts/shortlog.py "only('.', branch('stable') & tagged() & public() & not '.')" @@ -74,7 +74,7 @@ echo "Rebuild readthedocs for docs.kallithea-scm.org" xdg-open https://readthedocs.org/projects/kallithea/ curl -X POST http://readthedocs.org/build/kallithea -xdg-open https://readthedocs.org/builds/kallithea/ +xdg-open https://readthedocs.org/projects/kallithea/builds xdg-open http://docs.kallithea-scm.org/en/latest/ # or whatever the branch is twine upload dist/* diff -r 460e7d2d1b38 -r 928bc1d8b279 scripts/shortlog.py --- a/scripts/shortlog.py Sun Jan 05 01:19:05 2020 +0100 +++ b/scripts/shortlog.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @@ -9,7 +9,7 @@ import os from collections import Counter -import contributor_data +from . import contributor_data def main(): diff -r 460e7d2d1b38 -r 928bc1d8b279 scripts/update-copyrights.py --- a/scripts/update-copyrights.py Sun Jan 05 01:19:05 2020 +0100 +++ b/scripts/update-copyrights.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @@ -42,7 +42,7 @@ import re from collections import defaultdict -import contributor_data +from . import contributor_data def sortkey(x): @@ -51,7 +51,7 @@ * first contribution * number of contribution years * name (with some unicode normalization) - The entries must be 2-tuples of a list of string years and the unicode name""" + The entries must be 2-tuples of a list of string years and the name""" return (x[0] and -int(x[0][-1]), x[0] and int(x[0][0]), -len(x[0]), @@ -100,6 +100,9 @@ for year, name in all_entries: if name in no_entries or (name, year) in no_entries: continue + parts = name.split(' <', 1) + if len(parts) == 2: + name = parts[0] + ' <' + parts[1].lower() domain = name.split('@', 1)[-1].rstrip('>') if domain in domain_extra: name_years[domain_extra[domain]].add(year) diff -r 460e7d2d1b38 -r 928bc1d8b279 scripts/validate-commits --- a/scripts/validate-commits Sun Jan 05 01:19:05 2020 +0100 +++ b/scripts/validate-commits Thu Feb 06 01:19:23 2020 +0100 @@ -34,7 +34,7 @@ hg update "$rev" cleanup - virtualenv -p "$(command -v python2)" "$venv" + python3 -m venv "$venv" source "$venv/bin/activate" pip install --upgrade pip setuptools pip install -e . -r dev_requirements.txt python-ldap python-pam diff -r 460e7d2d1b38 -r 928bc1d8b279 scripts/validate-minimum-dependency-versions --- a/scripts/validate-minimum-dependency-versions Sun Jan 05 01:19:05 2020 +0100 +++ b/scripts/validate-minimum-dependency-versions Thu Feb 06 01:19:23 2020 +0100 @@ -28,14 +28,11 @@ sed -n 's/.*"\(.*\)>=\(.*\)".*/\1==\2/p' setup.py > "$min_requirements" sed 's/>=/==/p' dev_requirements.txt >> "$min_requirements" -virtualenv -p "$(command -v python2)" "$venv" +python3 -m venv "$venv" source "$venv/bin/activate" pip install --upgrade pip setuptools pip install -e . -r "$min_requirements" python-ldap python-pam 2> >(tee "$log" >&2) -# Strip out the known Python 2.7 deprecation message. -sed -i '/DEPRECATION: Python 2\.7 will reach the end of its life/d' "$log" - # Treat any message on stderr as a problem, for the caller to interpret. if [ -s "$log" ]; then echo diff -r 460e7d2d1b38 -r 928bc1d8b279 setup.py --- a/setup.py Sun Jan 05 01:19:05 2020 +0100 +++ b/setup.py Thu Feb 06 01:19:23 2020 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import platform @@ -9,8 +9,8 @@ from setuptools.command import sdist -if sys.version_info < (2, 6) or sys.version_info >= (3,): - raise Exception('Kallithea requires python 2.7') +if sys.version_info < (3, 6): + raise Exception('Kallithea requires Python 3.6 or later') here = os.path.abspath(os.path.dirname(__file__)) @@ -25,7 +25,7 @@ return callback_handler(eval(matches.groups()[0])) -_meta = open(os.path.join(here, 'kallithea', '__init__.py'), 'rb') +_meta = open(os.path.join(here, 'kallithea', '__init__.py'), 'r') _metadata = _meta.read() _meta.close() @@ -40,35 +40,36 @@ is_windows = __platform__ in ['Windows'] requirements = [ - "alembic >= 0.8.0, < 1.1", + "alembic >= 1.0.10, < 1.1", "gearbox >= 0.1.0, < 1", "waitress >= 0.8.8, < 1.4", - "WebOb >= 1.7, < 1.9", + "WebOb >= 1.8, < 1.9", "backlash >= 0.1.2, < 1", - "TurboGears2 >= 2.3.10, < 2.5", + "TurboGears2 >= 2.4, < 2.5", "tgext.routes >= 0.2.0, < 1", - "Beaker >= 1.7.0, < 2", - "WebHelpers >= 1.3, < 1.4", + "Beaker >= 1.10.1, < 2", "WebHelpers2 >= 2.0, < 2.1", - "FormEncode >= 1.3.0, < 1.4", - "SQLAlchemy >= 1.1, < 1.4", - "Mako >= 0.9.0, < 1.1", + "FormEncode >= 1.3.1, < 1.4", + "SQLAlchemy >= 1.2.9, < 1.4", + "Mako >= 0.9.1, < 1.1", "Pygments >= 2.2.0, < 2.5", - "Whoosh >= 2.5.0, < 2.8", + "Whoosh >= 2.7.1, < 2.8", "celery >= 3.1, < 4.0", # TODO: celery 4 doesn't work "Babel >= 1.3, < 2.8", - "python-dateutil >= 1.5.0, < 2.9", + "python-dateutil >= 2.1.0, < 2.9", "Markdown >= 2.2.1, < 3.2", "docutils >= 0.11, < 0.15", "URLObject >= 2.3.4, < 2.5", - "Routes >= 1.13, < 2", # TODO: bumping to 2.0 will make test_file_annotation fail - "dulwich >= 0.14.1, < 0.20", - "mercurial >= 4.5, < 5.3", - "decorator >= 3.3.2, < 4.5", + "Routes >= 2.0, < 2.5", + "dulwich >= 0.19.0, < 0.20", + "mercurial >= 5.2, < 5.4", + "decorator >= 4.2.1, < 4.5", "Paste >= 2.0.3, < 3.1", "bleach >= 3.0, < 3.2", "Click >= 7.0, < 8", - "ipaddr >= 2.1.10, < 2.3", + "ipaddr >= 2.2.0, < 2.3", + "paginate >= 0.5, < 0.6", + "paginate_sqlalchemy >= 0.3.0, < 0.4", ] if not is_windows: @@ -84,8 +85,9 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU General Public License (GPL)', 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Topic :: Software Development :: Version Control', ]