Changeset - aa3e860a1fe0
[Not reviewed]
Merge default
0 10 0
Mads Kiilerich (mads) - 5 years ago 2020-12-21 01:19:49
mads@kiilerich.com
Merge stable
2 files changed:
0 comments (0 inline, 0 general)
kallithea/controllers/api/api.py
Show inline comments
 
# -*- 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 <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.controllers.api.api
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
API controller for Kallithea
 

	
 
This file was forked by the Kallithea project in July 2014.
 
Original author and date, and relevant copyright and licensing information is below:
 
:created_on: Aug 20, 2011
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH, and others.
 
:license: GPLv3, see LICENSE.md for more details.
 
"""
 

	
 
import logging
 
import traceback
 
from datetime import datetime
 

	
 
from tg import request
 

	
 
from kallithea.controllers.api import JSONRPCController, JSONRPCError
 
from kallithea.lib.auth import (AuthUser, HasPermissionAny, HasPermissionAnyDecorator, HasRepoGroupPermissionLevel, HasRepoPermissionLevel,
 
                                HasUserGroupPermissionLevel)
 
from kallithea.lib.exceptions import DefaultUserException, UserGroupsAssignedException
 
from kallithea.lib.utils import repo2db_mapper
 
from kallithea.lib.vcs.backends.base import EmptyChangeset
 
from kallithea.lib.vcs.exceptions import EmptyRepositoryError
 
from kallithea.model import db, meta, userlog
 
from kallithea.model.changeset_status import ChangesetStatusModel
 
from kallithea.model.comment import ChangesetCommentsModel
 
from kallithea.model.gist import GistModel
 
from kallithea.model.pull_request import PullRequestModel
 
from kallithea.model.repo import RepoModel
 
from kallithea.model.repo_group import RepoGroupModel
 
from kallithea.model.scm import ScmModel, UserGroupList
 
from kallithea.model.user import UserModel
 
from kallithea.model.user_group import UserGroupModel
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def store_update(updates, attr, name):
 
    """
 
    Stores param in updates dict if it's not None (i.e. if user explicitly set
 
    a parameter). This allows easy updates of passed in params.
 
    """
 
    if attr is not None:
 
        updates[name] = attr
 

	
 

	
 
def get_user_or_error(userid):
 
    """
 
    Get user by id or name or return JsonRPCError if not found
 

	
 
    :param userid:
 
    """
 
    user = UserModel().get_user(userid)
 
    if user is None:
 
        raise JSONRPCError("user `%s` does not exist" % (userid,))
 
    return user
 

	
 

	
 
def get_repo_or_error(repoid):
 
    """
 
    Get repo by id or name or return JsonRPCError if not found
 

	
 
    :param repoid:
 
    """
 
    repo = RepoModel().get_repo(repoid)
 
    if repo is None:
 
        raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 
    return repo
 

	
 

	
 
def get_repo_group_or_error(repogroupid):
 
    """
 
    Get repo group by id or name or return JsonRPCError if not found
 

	
 
    :param repogroupid:
 
    """
 
    repo_group = db.RepoGroup.guess_instance(repogroupid)
 
    if repo_group is None:
 
        raise JSONRPCError(
 
            'repository group `%s` does not exist' % (repogroupid,))
 
    return repo_group
 

	
 

	
 
def get_user_group_or_error(usergroupid):
 
    """
 
    Get user group by id or name or return JsonRPCError if not found
 

	
 
    :param usergroupid:
 
    """
 
    user_group = UserGroupModel().get_group(usergroupid)
 
    if user_group is None:
 
        raise JSONRPCError('user group `%s` does not exist' % (usergroupid,))
 
    return user_group
 

	
 

	
 
def get_perm_or_error(permid, prefix=None):
 
    """
 
    Get permission by id or name or return JsonRPCError if not found
 

	
 
    :param permid:
 
    """
 
    perm = db.Permission.get_by_key(permid)
 
    if perm is None:
 
        raise JSONRPCError('permission `%s` does not exist' % (permid,))
 
    if prefix:
 
        if not perm.permission_name.startswith(prefix):
 
            raise JSONRPCError('permission `%s` is invalid, '
 
                               'should start with %s' % (permid, prefix))
 
    return perm
 

	
 

	
 
def get_gist_or_error(gistid):
 
    """
 
    Get gist by id or gist_access_id or return JsonRPCError if not found
 

	
 
    :param gistid:
 
    """
 
    gist = GistModel().get_gist(gistid)
 
    if gist is None:
 
        raise JSONRPCError('gist `%s` does not exist' % (gistid,))
 
    return gist
 

	
 

	
 
class ApiController(JSONRPCController):
 
    """
 
    API Controller
 

	
 
    The authenticated user can be found as request.authuser.
 

	
 
    Example function::
 

	
 
        def func(arg1, arg2,...):
 
            pass
 

	
 
    Each function should also **raise** JSONRPCError for any
 
    errors that happens.
 
    """
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def test(self, args):
 
        return args
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def pull(self, repoid, clone_uri=None):
 
        """
 
        Triggers a pull from remote location on given repo. Can be used to
 
        automatically keep remote repos up to date. This command can be executed
 
        only using api_key belonging to user with admin rights
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param clone_uri: repository URI to pull from (optional)
 
        :type clone_uri: str
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            "msg": "Pulled from `<repository name>`"
 
            "repository": "<repository name>"
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "Unable to pull changes from `<reponame>`"
 
          }
 

	
 
        """
 

	
 
        repo = get_repo_or_error(repoid)
 

	
 
        try:
 
            ScmModel().pull_changes(repo.repo_name,
 
                                    request.authuser.username,
 
                                    request.ip_addr,
 
                                    clone_uri=clone_uri)
 
            return dict(
 
                msg='Pulled from `%s`' % repo.repo_name,
 
                repository=repo.repo_name
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'Unable to pull changes from `%s`' % repo.repo_name
 
            )
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def rescan_repos(self, remove_obsolete=False):
 
        """
 
        Triggers rescan repositories action. If remove_obsolete is set
 
        than also delete repos that are in database but not in the filesystem.
 
        aka "clean zombies". This command can be executed only using api_key
 
        belonging to user with admin rights.
 

	
 
        :param remove_obsolete: deletes repositories from
 
            database that are not found on the filesystem
 
        :type remove_obsolete: Optional(bool)
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            'added': [<added repository name>,...]
 
            'removed': [<removed repository name>,...]
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            'Error occurred during rescan repositories action'
 
          }
 

	
 
        """
 

	
 
        try:
 
            rm_obsolete = remove_obsolete
 
            added, removed = repo2db_mapper(ScmModel().repo_scan(),
 
                                            remove_obsolete=rm_obsolete)
 
            return {'added': added, 'removed': removed}
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'Error occurred during rescan repositories action'
 
            )
 

	
 
    def invalidate_cache(self, repoid):
 
        """
 
        Invalidate cache for repository.
 
        This command can be executed only using api_key belonging to user with admin
 
        rights or regular user that have write or admin or write access to repository.
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            'msg': Cache for repository `<repository name>` was invalidated,
 
            'repository': <repository name>
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            'Error occurred during cache invalidation action'
 
          }
 

	
 
        """
 
        repo = get_repo_or_error(repoid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoPermissionLevel('write')(repo.repo_name):
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 

	
 
        try:
 
            ScmModel().mark_for_invalidation(repo.repo_name)
 
            return dict(
 
                msg='Cache for repository `%s` was invalidated' % (repoid,),
 
                repository=repo.repo_name
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'Error occurred during cache invalidation action'
 
            )
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_ip(self, userid=None):
 
        """
 
        Shows IP address as seen from Kallithea server, together with all
 
        defined IP addresses for given user. If userid is not passed data is
 
        returned for user who's calling this function.
 
        This command can be executed only using api_key belonging to user with
 
        admin rights.
 

	
 
        :param userid: username to show ips for
 
        :type userid: Optional(str or int)
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result : {
 
                         "server_ip_addr": "<ip_from_clien>",
 
                         "user_ips": [
 
                                        {
 
                                           "ip_addr": "<ip_with_mask>",
 
                                           "ip_range": ["<start_ip>", "<end_ip>"],
 
                                        },
 
                                        ...
 
                                     ]
 
            }
 

	
 
        """
 
        if userid is None:
 
            userid = request.authuser.user_id
 
        user = get_user_or_error(userid)
 
        ips = db.UserIpMap.query().filter(db.UserIpMap.user == user).all()
 
        return dict(
 
            server_ip_addr=request.ip_addr,
 
            user_ips=ips
 
        )
 

	
 
    # alias for old
 
    show_ip = get_ip
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_server_info(self):
 
        """
 
        return server info, including Kallithea version and installed packages
 

	
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            'modules': [<module name>,...]
 
            'py_version': <python version>,
 
            'platform': <platform type>,
 
            'kallithea_version': <kallithea version>
 
          }
 
          error :  null
 
        """
 
        return db.Setting.get_server_info()
 

	
 
    def get_user(self, userid=None):
 
        """
 
        Gets a user by username or user_id, Returns empty result if user is
 
        not found. If userid param is skipped it is set to id of user who is
 
        calling this method. This command can be executed only using api_key
 
        belonging to user with admin rights, or regular users that cannot
 
        specify different userid than theirs
 

	
 
        :param userid: user to get data for
 
        :type userid: Optional(str or int)
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: None if user does not exist or
 
                    {
 
                        "user_id" :     "<user_id>",
 
                        "api_key" :     "<api_key>",
 
                        "api_keys":     "[<list of all API keys including additional ones>]"
 
                        "username" :    "<username>",
 
                        "firstname":    "<firstname>",
 
                        "lastname" :    "<lastname>",
 
                        "email" :       "<email>",
 
                        "emails":       "[<list of all emails including additional ones>]",
 
                        "ip_addresses": "[<ip_address_for_user>,...]",
 
                        "active" :      "<bool: user active>",
 
                        "admin" :       "<bool: user is admin>",
 
                        "extern_name" : "<extern_name>",
 
                        "extern_type" : "<extern type>
 
                        "last_login":   "<last_login>",
 
                        "permissions": {
 
                            "global": ["hg.create.repository",
 
                                       "repository.read",
 
                                       "hg.register.manual_activate"],
 
                            "repositories": {"repo1": "repository.none"},
 
                            "repositories_groups": {"Group1": "group.read"}
 
                         },
 
                    }
 

	
 
            error:  null
 

	
 
        """
 
        if not HasPermissionAny('hg.admin')():
 
            # make sure normal user does not pass someone else userid,
 
            # he is not allowed to do that
 
            if userid is not None and userid != request.authuser.user_id:
 
                raise JSONRPCError(
 
                    'userid is not the same as your user'
 
                )
 

	
 
        if userid is None:
 
            userid = request.authuser.user_id
 

	
 
        user = get_user_or_error(userid)
 
        data = user.get_api_data()
 
        data['permissions'] = AuthUser(user_id=user.user_id).permissions
 
        return data
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_users(self):
 
        """
 
        Lists all existing users. This command can be executed only using api_key
 
        belonging to user with admin rights.
 

	
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: [<user_object>, ...]
 
            error:  null
 
        """
 

	
 
        return [
 
            user.get_api_data()
 
            for user in db.User.query()
 
                .order_by(db.User.username)
 
                .filter_by(is_default_user=False)
 
        ]
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def create_user(self, username, email, password='',
 
                    firstname='', lastname='',
 
                    active=True, admin=False,
 
                    extern_type=db.User.DEFAULT_AUTH_TYPE,
 
                    extern_name=''):
 
        """
 
        Creates new user. Returns new user object. This command can
 
        be executed only using api_key belonging to user with admin rights.
 

	
 
        :param username: new username
 
        :type username: str or int
 
        :param email: email
 
        :type email: str
 
        :param password: password
 
        :type password: Optional(str)
 
        :param firstname: firstname
 
        :type firstname: Optional(str)
 
        :param lastname: lastname
 
        :type lastname: Optional(str)
 
        :param active: active
 
        :type active: Optional(bool)
 
        :param admin: admin
 
        :type admin: Optional(bool)
 
        :param extern_name: name of extern
 
        :type extern_name: Optional(str)
 
        :param extern_type: extern_type
 
        :type extern_type: Optional(str)
 

	
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "created new user `<username>`",
 
                      "user": <user_obj>
 
                    }
 
            error:  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "user `<username>` already exist"
 
            or
 
            "email `<email>` already exist"
 
            or
 
            "failed to create user `<username>`"
 
          }
 

	
 
        """
 

	
 
        if db.User.get_by_username(username):
 
            raise JSONRPCError("user `%s` already exist" % (username,))
 

	
 
        if db.User.get_by_email(email):
 
            raise JSONRPCError("email `%s` already exist" % (email,))
 

	
 
        try:
 
            user = UserModel().create_or_update(
 
                username=username,
 
                password=password,
 
                email=email,
 
                firstname=firstname,
 
                lastname=lastname,
 
                active=active,
 
                admin=admin,
 
                extern_type=extern_type,
 
                extern_name=extern_name
 
            )
 
            meta.Session().commit()
 
            return dict(
 
                msg='created new user `%s`' % username,
 
                user=user.get_api_data()
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create user `%s`' % (username,))
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def update_user(self, userid, username=None,
 
                    email=None, password=None,
 
                    firstname=None, lastname=None,
 
                    active=None, admin=None,
 
                    extern_type=None, extern_name=None):
 
        """
 
        updates given user if such user exists. This command can
 
        be executed only using api_key belonging to user with admin rights.
 

	
 
        :param userid: userid to update
 
        :type userid: str or int
 
        :param username: new username
 
        :type username: str or int
 
        :param email: email
 
        :type email: str
 
        :param password: password
 
        :type password: Optional(str)
 
        :param firstname: firstname
 
        :type firstname: Optional(str)
 
        :param lastname: lastname
 
        :type lastname: Optional(str)
 
        :param active: active
 
        :type active: Optional(bool)
 
        :param admin: admin
 
        :type admin: Optional(bool)
 
        :param extern_name:
 
        :type extern_name: Optional(str)
 
        :param extern_type:
 
        :type extern_type: Optional(str)
 

	
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "updated user ID:<userid> <username>",
 
                      "user": <user_object>,
 
                    }
 
            error:  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to update user `<username>`"
 
          }
 

	
 
        """
 

	
 
        user = get_user_or_error(userid)
 

	
 
        # only non optional arguments will be stored in updates
 
        updates = {}
 

	
 
        try:
 

	
 
            store_update(updates, username, 'username')
 
            store_update(updates, password, 'password')
 
            store_update(updates, email, 'email')
 
            store_update(updates, firstname, 'name')
 
            store_update(updates, lastname, 'lastname')
 
            store_update(updates, active, 'active')
 
            store_update(updates, admin, 'admin')
 
            store_update(updates, extern_name, 'extern_name')
 
            store_update(updates, extern_type, 'extern_type')
 

	
 
            user = UserModel().update_user(user, **updates)
 
            meta.Session().commit()
 
            return dict(
 
                msg='updated user ID:%s %s' % (user.user_id, user.username),
 
                user=user.get_api_data()
 
            )
 
        except DefaultUserException:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('editing default user is forbidden')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to update user `%s`' % (userid,))
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def delete_user(self, userid):
 
        """
 
        deletes given user if such user exists. This command can
 
        be executed only using api_key belonging to user with admin rights.
 

	
 
        :param userid: user to delete
 
        :type userid: str or int
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "deleted user ID:<userid> <username>",
 
                      "user": null
 
                    }
 
            error:  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to delete user ID:<userid> <username>"
 
          }
 

	
 
        """
 
        user = get_user_or_error(userid)
 

	
 
        try:
 
            UserModel().delete(userid)
 
            meta.Session().commit()
 
            return dict(
 
                msg='deleted user ID:%s %s' % (user.user_id, user.username),
 
                user=None
 
            )
 
        except Exception:
 

	
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to delete user ID:%s %s'
 
                               % (user.user_id, user.username))
 

	
 
    # permission check inside
 
    def get_user_group(self, usergroupid):
 
        """
 
        Gets an existing user group. This command can be executed only using api_key
 
        belonging to user with admin rights or user who has at least
 
        read access to user group.
 

	
 
        :param usergroupid: id of user_group to edit
 
        :type usergroupid: str or int
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result : None if group not exist
 
                     {
 
                       "users_group_id" : "<id>",
 
                       "group_name" :     "<groupname>",
 
                       "active":          "<bool>",
 
                       "members" :  [<user_obj>,...]
 
                     }
 
            error : null
 

	
 
        """
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasUserGroupPermissionLevel('read')(user_group.users_group_name):
 
                raise JSONRPCError('user group `%s` does not exist' % (usergroupid,))
 

	
 
        data = user_group.get_api_data()
 
        return data
 

	
 
    # permission check inside
 
    def get_user_groups(self):
 
        """
 
        Lists all existing user groups. This command can be executed only using
 
        api_key belonging to user with admin rights or user who has at least
 
        read access to user group.
 

	
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result : [<user_group_obj>,...]
 
            error : null
 
        """
 

	
 
        return [
 
            user_group.get_api_data()
 
            for user_group in UserGroupList(db.UserGroup.query().all(), perm_level='read')
 
        ]
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
 
    def create_user_group(self, group_name, description='',
 
                          owner=None, active=True):
 
        """
 
        Creates new user group. This command can be executed only using api_key
 
        belonging to user with admin rights or an user who has create user group
 
        permission
 

	
 
        :param group_name: name of new user group
 
        :type group_name: str
 
        :param description: group description
 
        :type description: str
 
        :param owner: owner of group. If not passed apiuser is the owner
 
        :type owner: Optional(str or int)
 
        :param active: group is active
 
        :type active: Optional(bool)
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg": "created new user group `<groupname>`",
 
                      "user_group": <user_group_object>
 
                    }
 
            error:  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "user group `<group name>` already exist"
 
            or
 
            "failed to create group `<group name>`"
 
          }
 

	
 
        """
 

	
 
        if UserGroupModel().get_by_name(group_name):
 
            raise JSONRPCError("user group `%s` already exist" % (group_name,))
 

	
 
        try:
 
            if owner is None:
 
                owner = request.authuser.user_id
 

	
 
            owner = get_user_or_error(owner)
 
            ug = UserGroupModel().create(name=group_name, description=description,
 
                                         owner=owner, active=active)
 
            meta.Session().commit()
 
            return dict(
 
                msg='created new user group `%s`' % group_name,
 
                user_group=ug.get_api_data()
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create group `%s`' % (group_name,))
 

	
 
    # permission check inside
 
    def update_user_group(self, usergroupid, group_name=None,
 
                          description=None, owner=None,
 
                          active=None):
 
        """
 
        Updates given usergroup.  This command can be executed only using api_key
 
        belonging to user with admin rights or an admin of given user group
 

	
 
        :param usergroupid: id of user group to update
 
        :type usergroupid: str or int
 
        :param group_name: name of new user group
 
        :type group_name: str
 
        :param description: group description
 
        :type description: str
 
        :param owner: owner of group.
 
        :type owner: Optional(str or int)
 
        :param active: group is active
 
        :type active: Optional(bool)
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            "msg": 'updated user group ID:<user group id> <user group name>',
 
            "user_group": <user_group_object>
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to update user group `<user group name>`"
 
          }
 

	
 
        """
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasUserGroupPermissionLevel('admin')(user_group.users_group_name):
 
                raise JSONRPCError('user group `%s` does not exist' % (usergroupid,))
 

	
 
        if owner is not None:
 
            owner = get_user_or_error(owner)
 

	
 
        updates = {}
 
        store_update(updates, group_name, 'users_group_name')
 
        store_update(updates, description, 'user_group_description')
 
        store_update(updates, owner, 'owner')
 
        store_update(updates, active, 'users_group_active')
 
        try:
 
            UserGroupModel().update(user_group, updates)
 
            meta.Session().commit()
 
            return dict(
 
                msg='updated user group ID:%s %s' % (user_group.users_group_id,
 
                                                     user_group.users_group_name),
 
                user_group=user_group.get_api_data()
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to update user group `%s`' % (usergroupid,))
 

	
 
    # permission check inside
 
    def delete_user_group(self, usergroupid):
 
        """
 
        Delete given user group by user group id or name.
 
        This command can be executed only using api_key
 
        belonging to user with admin rights or an admin of given user group
 

	
 
        :param usergroupid:
 
        :type usergroupid: int
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            "msg": "deleted user group ID:<user_group_id> <user_group_name>"
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to delete user group ID:<user_group_id> <user_group_name>"
 
            or
 
            "RepoGroup assigned to <repo_groups_list>"
 
          }
 

	
 
        """
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasUserGroupPermissionLevel('admin')(user_group.users_group_name):
 
                raise JSONRPCError('user group `%s` does not exist' % (usergroupid,))
 

	
 
        try:
 
            UserGroupModel().delete(user_group)
 
            meta.Session().commit()
 
            return dict(
 
                msg='deleted user group ID:%s %s' %
 
                    (user_group.users_group_id, user_group.users_group_name),
 
                user_group=None
 
            )
 
        except UserGroupsAssignedException as e:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(str(e))
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to delete user group ID:%s %s' %
 
                               (user_group.users_group_id,
 
                                user_group.users_group_name)
 
                               )
 

	
 
    # permission check inside
 
    def add_user_to_user_group(self, usergroupid, userid):
 
        """
 
        Adds a user to a user group. If user exists in that group success will be
 
        `false`. This command can be executed only using api_key
 
        belonging to user with admin rights  or an admin of given user group
 

	
 
        :param usergroupid:
 
        :type usergroupid: int
 
        :param userid:
 
        :type userid: int
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
              "success": True|False # depends on if member is in group
 
              "msg": "added member `<username>` to user group `<groupname>` |
 
                      User is already in that group"
 

	
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to add member to user group `<user_group_name>`"
 
          }
 

	
 
        """
 
        user = get_user_or_error(userid)
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasUserGroupPermissionLevel('admin')(user_group.users_group_name):
 
                raise JSONRPCError('user group `%s` does not exist' % (usergroupid,))
 

	
 
        try:
 
            ugm = UserGroupModel().add_user_to_group(user_group, user)
 
            success = True if ugm is not True else False
 
            msg = 'added member `%s` to user group `%s`' % (
 
                user.username, user_group.users_group_name
 
            )
 
            msg = msg if success else 'User is already in that group'
 
            meta.Session().commit()
 

	
 
            return dict(
 
                success=success,
 
                msg=msg
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to add member to user group `%s`' % (
 
                    user_group.users_group_name,
 
                )
 
            )
 

	
 
    # permission check inside
 
    def remove_user_from_user_group(self, usergroupid, userid):
 
        """
 
        Removes a user from a user group. If user is not in given group success will
 
        be `false`. This command can be executed only
 
        using api_key belonging to user with admin rights or an admin of given user group
 

	
 
        :param usergroupid:
 
        :param userid:
 

	
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "success":  True|False,  # depends on if member is in group
 
                      "msg": "removed member <username> from user group <groupname> |
 
                              User wasn't in group"
 
                    }
 
            error:  null
 

	
 
        """
 
        user = get_user_or_error(userid)
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasUserGroupPermissionLevel('admin')(user_group.users_group_name):
 
                raise JSONRPCError('user group `%s` does not exist' % (usergroupid,))
 

	
 
        try:
 
            success = UserGroupModel().remove_user_from_group(user_group, user)
 
            msg = 'removed member `%s` from user group `%s`' % (
 
                user.username, user_group.users_group_name
 
            )
 
            msg = msg if success else "User wasn't in group"
 
            meta.Session().commit()
 
            return dict(success=success, msg=msg)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to remove member from user group `%s`' % (
 
                    user_group.users_group_name,
 
                )
 
            )
 

	
 
    # permission check inside
 
    def get_repo(self, repoid,
 
                 with_revision_names=False,
 
                 with_pullrequests=False):
 
        """
 
        Gets an existing repository by it's name or repository_id. Members will return
 
        either users_group or user associated to that repository. This command can be
 
        executed only using api_key belonging to user with admin
 
        rights or regular user that have at least read access to repository.
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            {
 
                "repo_id" :          "<repo_id>",
 
                "repo_name" :        "<reponame>"
 
                "repo_type" :        "<repo_type>",
 
                "clone_uri" :        "<clone_uri>",
 
                "enable_downloads":  "<bool>",
 
                "enable_statistics": "<bool>",
 
                "private":           "<bool>",
 
                "created_on" :       "<date_time_created>",
 
                "description" :      "<description>",
 
                "landing_rev":       "<landing_rev>",
 
                "last_changeset":    {
 
                                       "author":   "<full_author>",
 
                                       "date":     "<date_time_of_commit>",
 
                                       "message":  "<commit_message>",
 
                                       "raw_id":   "<raw_id>",
 
                                       "revision": "<numeric_revision>",
 
                                       "short_id": "<short_id>"
 
                                     }
 
                "owner":             "<repo_owner>",
 
                "fork_of":           "<name_of_fork_parent>",
 
                "members" :     [
 
                                  {
 
                                    "name":     "<username>",
 
                                    "type" :    "user",
 
                                    "permission" : "repository.(read|write|admin)"
 
                                  },
 
 
                                  {
 
                                    "name":     "<usergroup name>",
 
                                    "type" :    "user_group",
 
                                    "permission" : "usergroup.(read|write|admin)"
 
                                  },
 
 
                                ]
 
                 "followers":   [<user_obj>, ...],
 
                 <if with_revision_names == True>
 
                 "tags": {
 
                            "<tagname>": "<raw_id>",
 
                            ...
 
                         },
 
                 "branches": {
 
                            "<branchname>": "<raw_id>",
 
                            ...
 
                         },
 
                 "bookmarks": {
 
                            "<bookmarkname>": "<raw_id>",
 
                            ...
 
                         },
 
            }
 
          }
 
          error :  null
 

	
 
        """
 
        repo = get_repo_or_error(repoid)
 

	
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoPermissionLevel('read')(repo.repo_name):
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 

	
 
        members = []
 
        for user in repo.repo_to_perm:
 
            perm = user.permission.permission_name
 
            user = user.user
 
            user_data = {
 
                'name': user.username,
 
                'type': "user",
 
                'permission': perm
 
            }
 
            members.append(user_data)
 

	
 
        for user_group in repo.users_group_to_perm:
 
            perm = user_group.permission.permission_name
 
            user_group = user_group.users_group
 
            user_group_data = {
 
                'name': user_group.users_group_name,
 
                'type': "user_group",
 
                'permission': perm
 
            }
 
            members.append(user_group_data)
 

	
 
        followers = [
 
            uf.user.get_api_data()
 
            for uf in repo.followers
 
        ]
 

	
 
        data = repo.get_api_data(with_revision_names=with_revision_names,
 
                                 with_pullrequests=with_pullrequests)
 
        data['members'] = members
 
        data['followers'] = followers
 
        return data
 

	
 
    # permission check inside
 
    def get_repos(self):
 
        """
 
        Lists all existing repositories. This command can be executed only using
 
        api_key belonging to user with admin rights or regular user that have
 
        admin, write or read access to repository.
 

	
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: [
 
                      {
 
                        "repo_id" :          "<repo_id>",
 
                        "repo_name" :        "<reponame>"
 
                        "repo_type" :        "<repo_type>",
 
                        "clone_uri" :        "<clone_uri>",
 
                        "private": :         "<bool>",
 
                        "created_on" :       "<datetimecreated>",
 
                        "description" :      "<description>",
 
                        "landing_rev":       "<landing_rev>",
 
                        "owner":             "<repo_owner>",
 
                        "fork_of":           "<name_of_fork_parent>",
 
                        "enable_downloads":  "<bool>",
 
                        "enable_statistics": "<bool>",
 
                      },
 
 
                    ]
 
            error:  null
 
        """
 
        if not HasPermissionAny('hg.admin')():
 
            repos = request.authuser.get_all_user_repos()
 
        else:
 
            repos = db.Repository.query()
 

	
 
        return [
 
            repo.get_api_data()
 
            for repo in repos
 
        ]
 

	
 
    # permission check inside
 
    def get_repo_nodes(self, repoid, revision, root_path,
 
                       ret_type='all'):
 
        """
 
        returns a list of nodes and it's children in a flat list for a given path
 
        at given revision. It's possible to specify ret_type to show only `files` or
 
        `dirs`.  This command can be executed only using api_key belonging to
 
        user with admin rights or regular user that have at least read access to repository.
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param revision: revision for which listing should be done
 
        :type revision: str
 
        :param root_path: path from which start displaying
 
        :type root_path: str
 
        :param ret_type: return type 'all|files|dirs' nodes
 
        :type ret_type: Optional(str)
 

	
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: [
 
                      {
 
                        "name" :        "<name>"
 
                        "type" :        "<type>",
 
                      },
 
 
                    ]
 
            error:  null
 
        """
 
        repo = get_repo_or_error(repoid)
 

	
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoPermissionLevel('read')(repo.repo_name):
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 

	
 
        _map = {}
 
        try:
 
            _d, _f = ScmModel().get_nodes(repo, revision, root_path,
 
                                          flat=False)
 
            _map = {
 
                'all': _d + _f,
 
                'files': _f,
 
                'dirs': _d,
 
            }
 
            return _map[ret_type]
 
        except KeyError:
 
            raise JSONRPCError('ret_type must be one of %s'
 
                               % (','.join(sorted(_map))))
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to get repo: `%s` nodes' % repo.repo_name
 
            )
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
 
    def create_repo(self, repo_name, owner=None,
 
                    repo_type=None, description='',
 
                    private=False, clone_uri=None,
 
                    landing_rev='rev:tip',
 
                    enable_statistics=None,
 
                    enable_downloads=None,
 
                    copy_permissions=False):
 
        """
 
        Creates a repository. The repository name contains the full path, but the
 
        parent repository group must exist. For example "foo/bar/baz" require the groups
 
        "foo" and "bar" (with "foo" as parent), and create "baz" repository with
 
        "bar" as group. This command can be executed only using api_key
 
        belonging to user with admin rights or regular user that have create
 
        repository permission. Regular users cannot specify owner parameter
 

	
 
        :param repo_name: repository name
 
        :type repo_name: str
 
        :param owner: user_id or username
 
        :type owner: Optional(str)
 
        :param repo_type: 'hg' or 'git'
 
        :type repo_type: Optional(str)
 
        :param description: repository description
 
        :type description: Optional(str)
 
        :param private:
 
        :type private: bool
 
        :param clone_uri:
 
        :type clone_uri: str
 
        :param landing_rev: <rev_type>:<rev>
 
        :type landing_rev: str
 
        :param enable_downloads:
 
        :type enable_downloads: bool
 
        :param enable_statistics:
 
        :type enable_statistics: bool
 
        :param copy_permissions: Copy permission from group that repository is
 
            being created.
 
        :type copy_permissions: bool
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg": "Created new repository `<reponame>`",
 
                      "success": true,
 
                      "task": "<celery task id or None if done sync>"
 
                    }
 
            error:  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
             'failed to create repository `<repo_name>`
 
          }
 

	
 
        """
 
        if not HasPermissionAny('hg.admin')():
 
            if owner is not None:
 
                # forbid setting owner for non-admins
 
                raise JSONRPCError(
 
                    'Only Kallithea admin can specify `owner` param'
 
                )
 
        if owner is None:
 
            owner = request.authuser.user_id
 

	
 
        owner = get_user_or_error(owner)
 

	
 
        if RepoModel().get_by_repo_name(repo_name):
 
            raise JSONRPCError("repo `%s` already exist" % repo_name)
 

	
 
        defs = db.Setting.get_default_repo_settings(strip_prefix=True)
 
        if private is None:
 
            private = defs.get('repo_private') or False
 
        if repo_type is None:
 
            repo_type = defs.get('repo_type')
 
        if enable_statistics is None:
 
            enable_statistics = defs.get('repo_enable_statistics')
 
        if enable_downloads is None:
 
            enable_downloads = defs.get('repo_enable_downloads')
 

	
 
        try:
 
            repo_name_parts = repo_name.split('/')
 
            repo_group = None
 
            if len(repo_name_parts) > 1:
 
                group_name = '/'.join(repo_name_parts[:-1])
 
                repo_group = db.RepoGroup.get_by_group_name(group_name)
 
                if repo_group is None:
 
                    raise JSONRPCError("repo group `%s` not found" % group_name)
 
            data = dict(
 
                repo_name=repo_name_parts[-1],
 
                repo_name_full=repo_name,
 
                repo_type=repo_type,
 
                repo_description=description,
 
                owner=owner,
 
                repo_private=private,
 
                clone_uri=clone_uri,
 
                repo_group=repo_group,
 
                repo_landing_rev=landing_rev,
 
                enable_statistics=enable_statistics,
 
                enable_downloads=enable_downloads,
 
                repo_copy_permissions=copy_permissions,
 
            )
 

	
 
            task = RepoModel().create(form_data=data, cur_user=owner)
 
            task = RepoModel().create(form_data=data, cur_user=owner.username)
 
            task_id = task.task_id
 
            # no commit, it's done in RepoModel, or async via celery
 
            return dict(
 
                msg="Created new repository `%s`" % (repo_name,),
 
                success=True,  # cannot return the repo data here since fork
 
                               # can be done async
 
                task=task_id
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to create repository `%s`' % (repo_name,))
 

	
 
    # permission check inside
 
    def update_repo(self, repoid, name=None,
 
                    owner=None,
 
                    group=None,
 
                    description=None, private=None,
 
                    clone_uri=None, landing_rev=None,
 
                    enable_statistics=None,
 
                    enable_downloads=None):
 

	
 
        """
 
        Updates repo
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param name:
 
        :param owner:
 
        :param group:
 
        :param description:
 
        :param private:
 
        :param clone_uri:
 
        :param landing_rev:
 
        :param enable_statistics:
 
        :param enable_downloads:
 
        """
 
        repo = get_repo_or_error(repoid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoPermissionLevel('admin')(repo.repo_name):
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 

	
 
            if (name != repo.repo_name and
 
                not HasPermissionAny('hg.create.repository')()
 
            ):
 
                raise JSONRPCError('no permission to create (or move) repositories')
 

	
 
            if owner is not None:
 
                # forbid setting owner for non-admins
 
                raise JSONRPCError(
 
                    'Only Kallithea admin can specify `owner` param'
 
                )
 

	
 
        updates = {}
 
        repo_group = group
 
        if repo_group is not None:
 
            repo_group = get_repo_group_or_error(repo_group)
 
            repo_group = repo_group.group_id
 
        try:
 
            store_update(updates, name, 'repo_name')
 
            store_update(updates, repo_group, 'repo_group')
 
            store_update(updates, owner, 'owner')
 
            store_update(updates, description, 'repo_description')
 
            store_update(updates, private, 'repo_private')
 
            store_update(updates, clone_uri, 'clone_uri')
 
            store_update(updates, landing_rev, 'repo_landing_rev')
 
            store_update(updates, enable_statistics, 'repo_enable_statistics')
 
            store_update(updates, enable_downloads, 'repo_enable_downloads')
 

	
 
            RepoModel().update(repo, **updates)
 
            meta.Session().commit()
 
            return dict(
 
                msg='updated repo ID:%s %s' % (repo.repo_id, repo.repo_name),
 
                repository=repo.get_api_data()
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to update repo `%s`' % repoid)
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
 
    def fork_repo(self, repoid, fork_name,
 
                  owner=None,
 
                  description='', copy_permissions=False,
 
                  private=False, landing_rev='rev:tip'):
 
        """
 
        Creates a fork of given repo. In case of using celery this will
 
        immediately return success message, while fork is going to be created
 
        asynchronous. This command can be executed only using api_key belonging to
 
        user with admin rights or regular user that have fork permission, and at least
 
        read access to forking repository. Regular users cannot specify owner parameter.
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param fork_name:
 
        :param owner:
 
        :param description:
 
        :param copy_permissions:
 
        :param private:
 
        :param landing_rev:
 

	
 
        INPUT::
 

	
 
            id : <id_for_response>
 
            api_key : "<api_key>"
 
            args:     {
 
                        "repoid" :          "<reponame or repo_id>",
 
                        "fork_name":        "<forkname>",
 
                        "owner":            "<username or user_id = Optional(=apiuser)>",
 
                        "description":      "<description>",
 
                        "copy_permissions": "<bool>",
 
                        "private":          "<bool>",
 
                        "landing_rev":      "<landing_rev>"
 
                      }
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg": "Created fork of `<reponame>` as `<forkname>`",
 
                      "success": true,
 
                      "task": "<celery task id or None if done sync>"
 
                    }
 
            error:  null
 

	
 
        """
 
        repo = get_repo_or_error(repoid)
 
        repo_name = repo.repo_name
 

	
 
        _repo = RepoModel().get_by_repo_name(fork_name)
 
        if _repo:
 
            type_ = 'fork' if _repo.fork else 'repo'
 
            raise JSONRPCError("%s `%s` already exist" % (type_, fork_name))
 

	
 
        if HasPermissionAny('hg.admin')():
 
            pass
 
        elif HasRepoPermissionLevel('read')(repo.repo_name):
 
            if owner is not None:
 
                # forbid setting owner for non-admins
 
                raise JSONRPCError(
 
                    'Only Kallithea admin can specify `owner` param'
 
                )
 

	
 
            if not HasPermissionAny('hg.create.repository')():
 
                raise JSONRPCError('no permission to create repositories')
 
        else:
 
            raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 

	
 
        if owner is None:
 
            owner = request.authuser.user_id
 

	
 
        owner = get_user_or_error(owner)
 

	
 
        try:
 
            fork_name_parts = fork_name.split('/')
 
            repo_group = None
 
            if len(fork_name_parts) > 1:
 
                group_name = '/'.join(fork_name_parts[:-1])
 
                repo_group = db.RepoGroup.get_by_group_name(group_name)
 
                if repo_group is None:
 
                    raise JSONRPCError("repo group `%s` not found" % group_name)
 

	
 
            form_data = dict(
 
                repo_name=fork_name_parts[-1],
 
                repo_name_full=fork_name,
 
                repo_group=repo_group,
 
                repo_type=repo.repo_type,
 
                description=description,
 
                private=private,
 
                copy_permissions=copy_permissions,
 
                landing_rev=landing_rev,
 
                update_after_clone=False,
 
                fork_parent_id=repo.repo_id,
 
            )
 
            task = RepoModel().create_fork(form_data, cur_user=owner)
 
            task = RepoModel().create_fork(form_data, cur_user=owner.username)
 
            # no commit, it's done in RepoModel, or async via celery
 
            task_id = task.task_id
 
            return dict(
 
                msg='Created fork of `%s` as `%s`' % (repo.repo_name,
 
                                                      fork_name),
 
                success=True,  # cannot return the repo data here since fork
 
                               # can be done async
 
                task=task_id
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to fork repository `%s` as `%s`' % (repo_name,
 
                                                            fork_name)
 
            )
 

	
 
    # permission check inside
 
    def delete_repo(self, repoid, forks=''):
 
        """
 
        Deletes a repository. This command can be executed only using api_key belonging
 
        to user with admin rights or regular user that have admin access to repository.
 
        When `forks` param is set it's possible to detach or delete forks of deleting
 
        repository
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param forks: `detach` or `delete`, what do do with attached forks for repo
 
        :type forks: Optional(str)
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg": "Deleted repository `<reponame>`",
 
                      "success": true
 
                    }
 
            error:  null
 

	
 
        """
 
        repo = get_repo_or_error(repoid)
 

	
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoPermissionLevel('admin')(repo.repo_name):
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 

	
 
        try:
 
            handle_forks = forks
 
            _forks_msg = ''
 
            _forks = [f for f in repo.forks]
 
            if handle_forks == 'detach':
 
                _forks_msg = ' ' + 'Detached %s forks' % len(_forks)
 
            elif handle_forks == 'delete':
 
                _forks_msg = ' ' + 'Deleted %s forks' % len(_forks)
 
            elif _forks:
 
                raise JSONRPCError(
 
                    'Cannot delete `%s` it still contains attached forks' %
 
                    (repo.repo_name,)
 
                )
 

	
 
            RepoModel().delete(repo, forks=forks)
 
            meta.Session().commit()
 
            return dict(
 
                msg='Deleted repository `%s`%s' % (repo.repo_name, _forks_msg),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to delete repository `%s`' % (repo.repo_name,)
 
            )
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def grant_user_permission(self, repoid, userid, perm):
 
        """
 
        Grant permission for user on given repository, or update existing one
 
        if found. This command can be executed only using api_key belonging to user
 
        with admin rights.
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param userid:
 
        :param perm: (repository.(none|read|write|admin))
 
        :type perm: str
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
 
                      "success": true
 
                    }
 
            error:  null
 
        """
 
        repo = get_repo_or_error(repoid)
 
        user = get_user_or_error(userid)
 
        perm = get_perm_or_error(perm)
 

	
 
        try:
 

	
 
            RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
 

	
 
            meta.Session().commit()
 
            return dict(
 
                msg='Granted perm: `%s` for user: `%s` in repo: `%s`' % (
 
                    perm.permission_name, user.username, repo.repo_name
 
                ),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to edit permission for user: `%s` in repo: `%s`' % (
 
                    userid, repoid
 
                )
 
            )
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def revoke_user_permission(self, repoid, userid):
 
        """
 
        Revoke permission for user on given repository. This command can be executed
 
        only using api_key belonging to user with admin rights.
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param userid:
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
 
                      "success": true
 
                    }
 
            error:  null
 

	
 
        """
 

	
 
        repo = get_repo_or_error(repoid)
 
        user = get_user_or_error(userid)
 
        try:
 
            RepoModel().revoke_user_permission(repo=repo, user=user)
 
            meta.Session().commit()
 
            return dict(
 
                msg='Revoked perm for user: `%s` in repo: `%s`' % (
 
                    user.username, repo.repo_name
 
                ),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to edit permission for user: `%s` in repo: `%s`' % (
 
                    userid, repoid
 
                )
 
            )
 

	
 
    # permission check inside
 
    def grant_user_group_permission(self, repoid, usergroupid, perm):
 
        """
 
        Grant permission for user group on given repository, or update
 
        existing one if found. This command can be executed only using
 
        api_key belonging to user with admin rights.
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param usergroupid: id of usergroup
 
        :type usergroupid: str or int
 
        :param perm: (repository.(none|read|write|admin))
 
        :type perm: str
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
 
            "success": true
 

	
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to edit permission for user group: `<usergroup>` in repo `<repo>`'
 
          }
 

	
 
        """
 
        repo = get_repo_or_error(repoid)
 
        perm = get_perm_or_error(perm)
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoPermissionLevel('admin')(repo.repo_name):
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 

	
 
            if not HasUserGroupPermissionLevel('read')(user_group.users_group_name):
 
                raise JSONRPCError('user group `%s` does not exist' % (usergroupid,))
 

	
 
        try:
 
            RepoModel().grant_user_group_permission(
 
                repo=repo, group_name=user_group, perm=perm)
 

	
 
            meta.Session().commit()
 
            return dict(
 
                msg='Granted perm: `%s` for user group: `%s` in '
 
                    'repo: `%s`' % (
 
                        perm.permission_name, user_group.users_group_name,
 
                        repo.repo_name
 
                    ),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to edit permission for user group: `%s` in '
 
                'repo: `%s`' % (
 
                    usergroupid, repo.repo_name
 
                )
 
            )
 

	
 
    # permission check inside
 
    def revoke_user_group_permission(self, repoid, usergroupid):
 
        """
 
        Revoke permission for user group on given repository. This command can be
 
        executed only using api_key belonging to user with admin rights.
 

	
 
        :param repoid: repository name or repository id
 
        :type repoid: str or int
 
        :param usergroupid:
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
 
                      "success": true
 
                    }
 
            error:  null
 
        """
 
        repo = get_repo_or_error(repoid)
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoPermissionLevel('admin')(repo.repo_name):
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid,))
 

	
 
            if not HasUserGroupPermissionLevel('read')(user_group.users_group_name):
 
                raise JSONRPCError('user group `%s` does not exist' % (usergroupid,))
 

	
 
        try:
 
            RepoModel().revoke_user_group_permission(
 
                repo=repo, group_name=user_group)
 

	
 
            meta.Session().commit()
 
            return dict(
 
                msg='Revoked perm for user group: `%s` in repo: `%s`' % (
 
                    user_group.users_group_name, repo.repo_name
 
                ),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to edit permission for user group: `%s` in '
 
                'repo: `%s`' % (
 
                    user_group.users_group_name, repo.repo_name
 
                )
 
            )
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_repo_group(self, repogroupid):
 
        """
 
        Returns given repo group together with permissions, and repositories
 
        inside the group
 

	
 
        :param repogroupid: id/name of repository group
 
        :type repogroupid: str or int
 
        """
 
        repo_group = get_repo_group_or_error(repogroupid)
 

	
 
        members = []
 
        for user in repo_group.repo_group_to_perm:
 
            perm = user.permission.permission_name
 
            user = user.user
 
            user_data = {
 
                'name': user.username,
 
                'type': "user",
 
                'permission': perm
 
            }
 
            members.append(user_data)
 

	
 
        for user_group in repo_group.users_group_to_perm:
 
            perm = user_group.permission.permission_name
 
            user_group = user_group.users_group
 
            user_group_data = {
 
                'name': user_group.users_group_name,
 
                'type': "user_group",
 
                'permission': perm
 
            }
 
            members.append(user_group_data)
 

	
 
        data = repo_group.get_api_data()
 
        data["members"] = members
 
        return data
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def get_repo_groups(self):
 
        """
 
        Returns all repository groups
 

	
 
        """
 
        return [
 
            repo_group.get_api_data()
 
            for repo_group in db.RepoGroup.query()
 
        ]
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def create_repo_group(self, group_name, description='',
 
                          owner=None,
 
                          parent=None,
 
                          copy_permissions=False):
 
        """
 
        Creates a repository group. This command can be executed only using
 
        api_key belonging to user with admin rights.
 

	
 
        :param group_name:
 
        :type group_name:
 
        :param description:
 
        :type description:
 
        :param owner:
 
        :type owner:
 
        :param parent:
 
        :type parent:
 
        :param copy_permissions:
 
        :type copy_permissions:
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
              "msg": "created new repo group `<repo_group_name>`"
 
              "repo_group": <repogroup_object>
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            failed to create repo group `<repogroupid>`
 
          }
 

	
 
        """
 
        if db.RepoGroup.get_by_group_name(group_name):
 
            raise JSONRPCError("repo group `%s` already exist" % (group_name,))
 

	
 
        if owner is None:
 
            owner = request.authuser.user_id
 
        group_description = description
 
        parent_group = None
 
        if parent is not None:
 
            parent_group = get_repo_group_or_error(parent)
 

	
 
        try:
 
            repo_group = RepoGroupModel().create(
 
                group_name=group_name,
 
                group_description=group_description,
 
                owner=owner,
 
                parent=parent_group,
 
                copy_permissions=copy_permissions
 
            )
 
            meta.Session().commit()
 
            return dict(
 
                msg='created new repo group `%s`' % group_name,
 
                repo_group=repo_group.get_api_data()
 
            )
 
        except Exception:
 

	
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create repo group `%s`' % (group_name,))
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def update_repo_group(self, repogroupid, group_name=None,
 
                          description=None,
 
                          owner=None,
 
                          parent=None):
 
        repo_group = get_repo_group_or_error(repogroupid)
 

	
 
        updates = {}
 
        try:
 
            store_update(updates, group_name, 'group_name')
 
            store_update(updates, description, 'group_description')
 
            store_update(updates, owner, 'owner')
 
            store_update(updates, parent, 'parent_group')
 
            repo_group = RepoGroupModel().update(repo_group, updates)
 
            meta.Session().commit()
 
            return dict(
 
                msg='updated repository group ID:%s %s' % (repo_group.group_id,
 
                                                           repo_group.group_name),
 
                repo_group=repo_group.get_api_data()
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to update repository group `%s`'
 
                               % (repogroupid,))
 

	
 
    @HasPermissionAnyDecorator('hg.admin')
 
    def delete_repo_group(self, repogroupid):
 
        """
 

	
 
        :param repogroupid: name or id of repository group
 
        :type repogroupid: str or int
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            'msg': 'deleted repo group ID:<repogroupid> <repogroupname>
 
            'repo_group': null
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to delete repo group ID:<repogroupid> <repogroupname>"
 
          }
 

	
 
        """
 
        repo_group = get_repo_group_or_error(repogroupid)
 

	
 
        try:
 
            RepoGroupModel().delete(repo_group)
 
            meta.Session().commit()
 
            return dict(
 
                msg='deleted repo group ID:%s %s' %
 
                    (repo_group.group_id, repo_group.group_name),
 
                repo_group=None
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to delete repo group ID:%s %s' %
 
                               (repo_group.group_id, repo_group.group_name)
 
                               )
 

	
 
    # permission check inside
 
    def grant_user_permission_to_repo_group(self, repogroupid, userid,
 
                                            perm, apply_to_children='none'):
 
        """
 
        Grant permission for user on given repository group, or update existing
 
        one if found. This command can be executed only using api_key belonging
 
        to user with admin rights, or user who has admin right to given repository
 
        group.
 

	
 
        :param repogroupid: name or id of repository group
 
        :type repogroupid: str or int
 
        :param userid:
 
        :param perm: (group.(none|read|write|admin))
 
        :type perm: str
 
        :param apply_to_children: 'none', 'repos', 'groups', 'all'
 
        :type apply_to_children: str
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "Granted perm: `<perm>` (recursive:<apply_to_children>) for user: `<username>` in repo group: `<repo_group_name>`",
 
                      "success": true
 
                    }
 
            error:  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to edit permission for user: `<userid>` in repo group: `<repo_group_name>`"
 
          }
 

	
 
        """
 

	
 
        repo_group = get_repo_group_or_error(repogroupid)
 

	
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoGroupPermissionLevel('admin')(repo_group.group_name):
 
                raise JSONRPCError('repository group `%s` does not exist' % (repogroupid,))
 

	
 
        user = get_user_or_error(userid)
 
        perm = get_perm_or_error(perm, prefix='group.')
 

	
 
        try:
 
            RepoGroupModel().add_permission(repo_group=repo_group,
 
                                            obj=user,
 
                                            obj_type="user",
 
                                            perm=perm,
 
                                            recursive=apply_to_children)
 
            meta.Session().commit()
 
            return dict(
 
                msg='Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % (
 
                    perm.permission_name, apply_to_children, user.username, repo_group.name
 
                ),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to edit permission for user: `%s` in repo group: `%s`' % (
 
                    userid, repo_group.name))
 

	
 
    # permission check inside
 
    def revoke_user_permission_from_repo_group(self, repogroupid, userid,
 
                                               apply_to_children='none'):
 
        """
 
        Revoke permission for user on given repository group. This command can
 
        be executed only using api_key belonging to user with admin rights, or
 
        user who has admin right to given repository group.
 

	
 
        :param repogroupid: name or id of repository group
 
        :type repogroupid: str or int
 
        :param userid:
 
        :type userid:
 
        :param apply_to_children: 'none', 'repos', 'groups', 'all'
 
        :type apply_to_children: str
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "Revoked perm (recursive:<apply_to_children>) for user: `<username>` in repo group: `<repo_group_name>`",
 
                      "success": true
 
                    }
 
            error:  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to edit permission for user: `<userid>` in repo group: `<repo_group_name>`"
 
          }
 

	
 
        """
 

	
 
        repo_group = get_repo_group_or_error(repogroupid)
 

	
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoGroupPermissionLevel('admin')(repo_group.group_name):
 
                raise JSONRPCError('repository group `%s` does not exist' % (repogroupid,))
 

	
 
        user = get_user_or_error(userid)
 

	
 
        try:
 
            RepoGroupModel().delete_permission(repo_group=repo_group,
 
                                               obj=user,
 
                                               obj_type="user",
 
                                               recursive=apply_to_children)
 

	
 
            meta.Session().commit()
 
            return dict(
 
                msg='Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % (
 
                    apply_to_children, user.username, repo_group.name
 
                ),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to edit permission for user: `%s` in repo group: `%s`' % (
 
                    userid, repo_group.name))
 

	
 
    # permission check inside
 
    def grant_user_group_permission_to_repo_group(
 
            self, repogroupid, usergroupid, perm,
 
            apply_to_children='none'):
 
        """
 
        Grant permission for user group on given repository group, or update
 
        existing one if found. This command can be executed only using
 
        api_key belonging to user with admin rights, or user who has admin
 
        right to given repository group.
 

	
 
        :param repogroupid: name or id of repository group
 
        :type repogroupid: str or int
 
        :param usergroupid: id of usergroup
 
        :type usergroupid: str or int
 
        :param perm: (group.(none|read|write|admin))
 
        :type perm: str
 
        :param apply_to_children: 'none', 'repos', 'groups', 'all'
 
        :type apply_to_children: str
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            "msg" : "Granted perm: `<perm>` (recursive:<apply_to_children>) for user group: `<usersgroupname>` in repo group: `<repo_group_name>`",
 
            "success": true
 

	
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to edit permission for user group: `<usergroup>` in repo group: `<repo_group_name>`"
 
          }
 

	
 
        """
 
        repo_group = get_repo_group_or_error(repogroupid)
 
        perm = get_perm_or_error(perm, prefix='group.')
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoGroupPermissionLevel('admin')(repo_group.group_name):
 
                raise JSONRPCError(
 
                    'repository group `%s` does not exist' % (repogroupid,))
 

	
 
            if not HasUserGroupPermissionLevel('read')(user_group.users_group_name):
 
                raise JSONRPCError(
 
                    'user group `%s` does not exist' % (usergroupid,))
 

	
 
        try:
 
            RepoGroupModel().add_permission(repo_group=repo_group,
 
                                            obj=user_group,
 
                                            obj_type="user_group",
 
                                            perm=perm,
 
                                            recursive=apply_to_children)
 
            meta.Session().commit()
 
            return dict(
 
                msg='Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % (
 
                    perm.permission_name, apply_to_children,
 
                    user_group.users_group_name, repo_group.name
 
                ),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to edit permission for user group: `%s` in '
 
                'repo group: `%s`' % (
 
                    usergroupid, repo_group.name
 
                )
 
            )
 

	
 
    # permission check inside
 
    def revoke_user_group_permission_from_repo_group(
 
            self, repogroupid, usergroupid,
 
            apply_to_children='none'):
 
        """
 
        Revoke permission for user group on given repository. This command can be
 
        executed only using api_key belonging to user with admin rights, or
 
        user who has admin right to given repository group.
 

	
 
        :param repogroupid: name or id of repository group
 
        :type repogroupid: str or int
 
        :param usergroupid:
 
        :param apply_to_children: 'none', 'repos', 'groups', 'all'
 
        :type apply_to_children: str
 

	
 
        OUTPUT::
 

	
 
            id : <id_given_in_input>
 
            result: {
 
                      "msg" : "Revoked perm (recursive:<apply_to_children>) for user group: `<usersgroupname>` in repo group: `<repo_group_name>`",
 
                      "success": true
 
                    }
 
            error:  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to edit permission for user group: `<usergroup>` in repo group: `<repo_group_name>`"
 
          }
 

	
 

	
 
        """
 
        repo_group = get_repo_group_or_error(repogroupid)
 
        user_group = get_user_group_or_error(usergroupid)
 
        if not HasPermissionAny('hg.admin')():
 
            if not HasRepoGroupPermissionLevel('admin')(repo_group.group_name):
 
                raise JSONRPCError(
 
                    'repository group `%s` does not exist' % (repogroupid,))
 

	
 
            if not HasUserGroupPermissionLevel('read')(user_group.users_group_name):
 
                raise JSONRPCError(
 
                    'user group `%s` does not exist' % (usergroupid,))
 

	
 
        try:
 
            RepoGroupModel().delete_permission(repo_group=repo_group,
 
                                               obj=user_group,
 
                                               obj_type="user_group",
 
                                               recursive=apply_to_children)
 
            meta.Session().commit()
 
            return dict(
 
                msg='Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % (
 
                    apply_to_children, user_group.users_group_name, repo_group.name
 
                ),
 
                success=True
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to edit permission for user group: `%s` in repo group: `%s`' % (
 
                    user_group.users_group_name, repo_group.name
 
                )
 
            )
 

	
 
    def get_gist(self, gistid):
 
        """
 
        Get given gist by id
 

	
 
        :param gistid: id of private or public gist
 
        :type gistid: str
 
        """
 
        gist = get_gist_or_error(gistid)
 
        if not HasPermissionAny('hg.admin')():
 
            if gist.owner_id != request.authuser.user_id:
 
                raise JSONRPCError('gist `%s` does not exist' % (gistid,))
 
        return gist.get_api_data()
 

	
 
    def get_gists(self, userid=None):
 
        """
 
        Get all gists for given user. If userid is empty returned gists
 
        are for user who called the api
 

	
 
        :param userid: user to get gists for
 
        :type userid: Optional(str or int)
 
        """
 
        if not HasPermissionAny('hg.admin')():
 
            # make sure normal user does not pass someone else userid,
 
            # he is not allowed to do that
 
            if userid is not None and userid != request.authuser.user_id:
 
                raise JSONRPCError(
 
                    'userid is not the same as your user'
 
                )
 

	
 
        if userid is None:
 
            user_id = request.authuser.user_id
 
        else:
 
            user_id = get_user_or_error(userid).user_id
 

	
 
        return [
 
            gist.get_api_data()
 
            for gist in db.Gist().query()
 
                .filter_by(is_expired=False)
 
                .filter(db.Gist.owner_id == user_id)
 
                .order_by(db.Gist.created_on.desc())
 
        ]
 

	
 
    def create_gist(self, files, owner=None,
 
                    gist_type=db.Gist.GIST_PUBLIC, lifetime=-1,
 
                    description=''):
 

	
 
        """
 
        Creates new Gist
 

	
 
        :param files: files to be added to gist
 
            {'filename': {'content':'...', 'lexer': null},
 
             'filename2': {'content':'...', 'lexer': null}}
 
        :type files: dict
 
        :param owner: gist owner, defaults to api method caller
 
        :type owner: Optional(str or int)
 
        :param gist_type: type of gist 'public' or 'private'
 
        :type gist_type: Optional(str)
 
        :param lifetime: time in minutes of gist lifetime
 
        :type lifetime: Optional(int)
 
        :param description: gist description
 
        :type description: Optional(str)
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            "msg": "created new gist",
 
            "gist": {}
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to create gist"
 
          }
 

	
 
        """
 
        try:
 
            if owner is None:
 
                owner = request.authuser.user_id
 

	
 
            owner = get_user_or_error(owner)
 

	
 
            gist = GistModel().create(description=description,
 
                                      owner=owner,
 
                                      ip_addr=request.ip_addr,
 
                                      gist_mapping=files,
 
                                      gist_type=gist_type,
 
                                      lifetime=lifetime)
 
            meta.Session().commit()
 
            return dict(
 
                msg='created new gist',
 
                gist=gist.get_api_data()
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create gist')
 

	
 
    # permission check inside
 
    def delete_gist(self, gistid):
 
        """
 
        Deletes existing gist
 

	
 
        :param gistid: id of gist to delete
 
        :type gistid: str
 

	
 
        OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : {
 
            "deleted gist ID: <gist_id>",
 
            "gist": null
 
          }
 
          error :  null
 

	
 
        ERROR OUTPUT::
 

	
 
          id : <id_given_in_input>
 
          result : null
 
          error :  {
 
            "failed to delete gist ID:<gist_id>"
 
          }
 

	
 
        """
 
        gist = get_gist_or_error(gistid)
 
        if not HasPermissionAny('hg.admin')():
 
            if gist.owner_id != request.authuser.user_id:
 
                raise JSONRPCError('gist `%s` does not exist' % (gistid,))
 

	
 
        try:
 
            GistModel().delete(gist)
 
            meta.Session().commit()
 
            return dict(
 
                msg='deleted gist ID:%s' % (gist.gist_access_id,),
 
                gist=None
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to delete gist ID:%s'
 
                               % (gist.gist_access_id,))
 

	
 
    # permission check inside
 
    def get_changesets(self, repoid, start=None, end=None, start_date=None,
 
                       end_date=None, branch_name=None, reverse=False, with_file_list=False, max_revisions=None):
 
        repo = get_repo_or_error(repoid)
 
        if not HasRepoPermissionLevel('read')(repo.repo_name):
 
            raise JSONRPCError('Access denied to repo %s' % repo.repo_name)
 

	
 
        format = "%Y-%m-%dT%H:%M:%S"
 
        try:
 
            return [e.__json__(with_file_list) for e in
 
                repo.scm_instance.get_changesets(start,
 
                                                 end,
 
                                                 datetime.strptime(start_date, format) if start_date else None,
 
                                                 datetime.strptime(end_date, format) if end_date else None,
 
                                                 branch_name,
 
                                                 reverse, max_revisions)]
 
        except EmptyRepositoryError as e:
 
            raise JSONRPCError('Repository is empty')
 

	
 
    # permission check inside
 
    def get_changeset(self, repoid, raw_id, with_reviews=False):
 
        repo = get_repo_or_error(repoid)
 
        if not HasRepoPermissionLevel('read')(repo.repo_name):
 
            raise JSONRPCError('Access denied to repo %s' % repo.repo_name)
 
        changeset = repo.get_changeset(raw_id)
 
        if isinstance(changeset, EmptyChangeset):
 
            raise JSONRPCError('Changeset %s does not exist' % raw_id)
 

	
 
        info = dict(changeset.as_dict())
 

	
 
        if with_reviews:
 
            reviews = ChangesetStatusModel().get_statuses(
 
                                repo.repo_name, raw_id)
 
            info["reviews"] = reviews
 

	
 
        return info
 

	
 
    # permission check inside
 
    def get_pullrequest(self, pullrequest_id):
 
        """
 
        Get given pull request by id
 
        """
 
        pull_request = db.PullRequest.get(pullrequest_id)
 
        if pull_request is None:
 
            raise JSONRPCError('pull request `%s` does not exist' % (pullrequest_id,))
 
        if not HasRepoPermissionLevel('read')(pull_request.org_repo.repo_name):
 
            raise JSONRPCError('not allowed')
 
        return pull_request.get_api_data()
 

	
 
    # permission check inside
 
    def comment_pullrequest(self, pull_request_id, comment_msg='', status=None, close_pr=False):
 
        """
 
        Add comment, close and change status of pull request.
 
        """
 
        apiuser = get_user_or_error(request.authuser.user_id)
 
        pull_request = db.PullRequest.get(pull_request_id)
 
        if pull_request is None:
 
            raise JSONRPCError('pull request `%s` does not exist' % (pull_request_id,))
 
        if (not HasRepoPermissionLevel('read')(pull_request.org_repo.repo_name)):
 
            raise JSONRPCError('No permission to add comment. User needs at least reading permissions'
 
                               ' to the source repository.')
 
        owner = apiuser.user_id == pull_request.owner_id
 
        reviewer = apiuser.user_id in [reviewer.user_id for reviewer in pull_request.reviewers]
 
        if close_pr and not (apiuser.admin or owner):
 
            raise JSONRPCError('No permission to close pull request. User needs to be admin or owner.')
 
        if status and not (apiuser.admin or owner or reviewer):
 
            raise JSONRPCError('No permission to change pull request status. User needs to be admin, owner or reviewer.')
 
        if pull_request.is_closed():
 
            raise JSONRPCError('pull request is already closed')
 

	
 
        comment = ChangesetCommentsModel().create(
 
            text=comment_msg,
 
            repo=pull_request.org_repo.repo_id,
 
            author=apiuser.user_id,
 
            pull_request=pull_request.pull_request_id,
 
            f_path=None,
 
            line_no=None,
 
            status_change=db.ChangesetStatus.get_status_lbl(status),
 
            closing_pr=close_pr
 
        )
 
        userlog.action_logger(apiuser,
 
                      'user_commented_pull_request:%s' % pull_request_id,
 
                      pull_request.org_repo, request.ip_addr)
 
        if status:
 
            ChangesetStatusModel().set_status(
 
                pull_request.org_repo_id,
 
                status,
 
                apiuser.user_id,
 
                comment,
 
                pull_request=pull_request_id
 
            )
 
        if close_pr:
 
            PullRequestModel().close_pull_request(pull_request_id)
 
            userlog.action_logger(apiuser,
 
                          'user_closed_pull_request:%s' % pull_request_id,
 
                          pull_request.org_repo, request.ip_addr)
 
        meta.Session().commit()
 
        return True
 

	
 
    # permission check inside
 
    def edit_reviewers(self, pull_request_id, add=None, remove=None):
 
        """
 
        Add and/or remove one or more reviewers to a pull request, by username
 
        or user ID. Reviewers are specified either as a single-user string or
 
        as a JSON list of one or more strings.
 
        """
 
        if add is None and remove is None:
 
            raise JSONRPCError('''Invalid request. Neither 'add' nor 'remove' is specified.''')
 

	
 
        pull_request = db.PullRequest.get(pull_request_id)
 
        if pull_request is None:
 
            raise JSONRPCError('pull request `%s` does not exist' % (pull_request_id,))
 

	
 
        apiuser = get_user_or_error(request.authuser.user_id)
 
        is_owner = apiuser.user_id == pull_request.owner_id
 
        is_repo_admin = HasRepoPermissionLevel('admin')(pull_request.other_repo.repo_name)
 
        if not (apiuser.admin or is_repo_admin or is_owner):
 
            raise JSONRPCError('No permission to edit reviewers of this pull request. User needs to be admin or pull request owner.')
 
        if pull_request.is_closed():
 
            raise JSONRPCError('Cannot edit reviewers of a closed pull request.')
 

	
 
        if not isinstance(add, list):
 
            add = [add]
 
        if not isinstance(remove, list):
 
            remove = [remove]
 

	
 
        # look up actual user objects from given name or id. Bail out if unknown.
 
        add_objs = set(get_user_or_error(user) for user in add if user is not None)
 
        remove_objs = set(get_user_or_error(user) for user in remove if user is not None)
 

	
 
        new_reviewers = redundant_reviewers = set()
 
        if add_objs:
 
            new_reviewers, redundant_reviewers = PullRequestModel().add_reviewers(apiuser, pull_request, add_objs)
 
        if remove_objs:
 
            PullRequestModel().remove_reviewers(apiuser, pull_request, remove_objs)
 

	
 
        meta.Session().commit()
 

	
 
        return {
 
            'added': [x.username for x in new_reviewers],
 
            'already_present': [x.username for x in redundant_reviewers],
 
            # NOTE: no explicit check that removed reviewers were actually present.
 
            'removed': [x.username for x in remove_objs],
 
        }
kallithea/i18n/de/LC_MESSAGES/kallithea.po
Show inline comments
 
# Copyright (C) 2014 RhodeCode GmbH, and others.
 
# This file is distributed under the same license as the Kallithea project.
 

	
 
msgid ""
 
msgstr ""
 
"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
 
"Language: de\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"
 

	
 
msgid "There are no changesets yet"
 
msgstr "Es gibt noch keine Änderungssätze"
 

	
 
msgid "None"
 
msgstr "Keine"
 

	
 
msgid "(closed)"
 
msgstr "(geschlossen)"
 

	
 
msgid "Show whitespace"
 
msgstr "Zeige unsichtbare Zeichen"
 

	
 
msgid "Ignore whitespace"
 
msgstr "Ignoriere unsichtbare Zeichen"
 

	
 
msgid "Increase diff context to %(num)s lines"
 
msgstr "Erhöhe diff-Kontext auf %(num)s Zeilen"
 

	
 
msgid "Successfully deleted pull request %s"
 
msgstr "Pull-Request %s erfolgreich gelöscht"
 

	
 
msgid "Such revision does not exist for this repository"
 
msgstr "Die angegebene Version existiert nicht in diesem Repository"
 

	
 
msgid "Cannot show empty diff"
 
msgstr "Kann leeren diff nicht anzeigen"
 

	
 
msgid "No ancestor found for merge diff"
 
msgstr "Es konnte kein Vorfahre für den merge diff gefunden werden"
 

	
 
msgid "Multiple merge ancestors found for merge compare"
 
msgstr "Es wurden mehrere merge Vorfahren für den merge Vergleich gefunden"
 

	
 
msgid "Cannot compare repositories without using common ancestor"
 
msgstr ""
 
"Ohne einen gemeinsamen Vorfahren ist ein Vergleich der Repositories nicht "
 
"möglich"
 

	
 
msgid "No response"
 
msgstr "Keine Rückmeldung"
 

	
 
msgid "Unknown error"
 
msgstr "Unbekannter Fehler"
 

	
 
msgid ""
 
"The request could not be understood by the server due to malformed syntax."
 
msgstr ""
 
"Die Anfrage konnte wegen ungültiger Syntax vom Server nicht ausgewertet "
 
"werden."
 

	
 
msgid "Unauthorized access to resource"
 
msgstr "Unauthorisierter Zugang zur Ressource"
 

	
 
msgid "You don't have permission to view this page"
 
msgstr "Du hast keine Rechte, um diese Seite zu betrachten"
 

	
 
msgid "The resource could not be found"
 
msgstr "Die Ressource konnte nicht gefunden werden"
 

	
 
msgid ""
 
"The server encountered an unexpected condition which prevented it from "
 
"fulfilling the request."
 
msgstr ""
 
"Aufgrund einer unerwarteten Gegebenheit konnte der Server diese Anfrage "
 
"nicht vollenden."
 

	
 
msgid "%s committed on %s"
 
msgstr "%s committed am %s"
 

	
 
msgid "Changeset was too big and was cut off..."
 
msgstr "Der Änderungssatz war zu groß und wurde abgeschnitten..."
 

	
 
msgid "%s %s feed"
 
msgstr "%s %s Feed"
 

	
 
msgid "Changes on %s repository"
 
msgstr "Änderungen im %s Repository"
 

	
 
msgid "Click here to add new file"
 
msgstr "Hier klicken, um eine neue Datei hinzuzufügen"
 

	
 
msgid "%s at %s"
 
msgstr "%s auf %s"
 

	
 
msgid "Deleted file %s via Kallithea"
 
msgstr "Datei %s via Kallithea gelöscht"
 

	
 
msgid "Successfully deleted file %s"
 
msgstr "Datei %s erfolgreich gelöscht"
 

	
 
msgid "Error occurred during commit"
 
msgstr "Während des Commits trat ein Fehler auf"
 

	
 
msgid "Edited file %s via Kallithea"
 
msgstr "Datei %s via Kallithea editiert"
 

	
 
msgid "No changes"
 
msgstr "Keine Änderungen"
 

	
 
msgid "Successfully committed to %s"
 
msgstr "Der Commit zu %s war erfolgreich"
 

	
 
msgid "Added file via Kallithea"
 
msgstr "Datei via Kallithea hinzugefügt"
 

	
 
msgid "No content"
 
msgstr "Kein Inhalt"
 

	
 
msgid "No filename"
 
msgstr "Kein Dateiname"
 

	
 
msgid "Location must be relative path and must not contain .. in path"
 
msgstr "Der Ort muss ein relativer Pfad sein und darf nicht .. enthalten"
 

	
 
msgid "Downloads disabled"
 
msgstr "Downloads gesperrt"
 

	
 
msgid "Unknown revision %s"
 
msgstr "Unbekannte Revision %s"
 

	
 
msgid "Empty repository"
 
msgstr "Leeres Repository"
 

	
 
msgid "Unknown archive type"
 
msgstr "Unbekannter Archivtyp"
 

	
 
msgid "Changesets"
 
msgstr "Änderungssätze"
 

	
 
msgid "Branches"
 
msgstr "Entwicklungszweige"
 

	
 
msgid "Tags"
 
msgstr "Tags"
 

	
 
msgid "An error occurred during repository forking %s"
 
msgstr "Während des Forkens des Repositorys trat ein Fehler auf: %s"
 

	
 
msgid "Groups"
 
msgstr "Gruppen"
 

	
 
msgid "Repositories"
 
msgstr "Repositories"
 

	
 
msgid "Branch"
 
msgstr "Zweig"
 

	
 
msgid "Closed Branches"
 
msgstr "Geschlossene Branches"
 

	
 
msgid "Tag"
 
msgstr "Marke"
 

	
 
msgid "Bookmark"
 
msgstr "Lesezeichen"
 

	
 
msgid "Public Journal"
 
msgstr "Öffentliches Logbuch"
 

	
 
msgid "Journal"
 
msgstr "Logbuch"
 

	
 
msgid "Bad captcha"
 
msgstr "Falsches Captcha"
 

	
 
msgid "You have successfully registered with %s"
 
msgstr "Sie haben sich erfolgreich bei %s registriert"
 

	
 
msgid "A password reset confirmation code has been sent"
 
msgstr "Ihr Link um das Passwort zurückzusetzen wurde versendet"
 

	
 
msgid "Invalid password reset token"
 
msgstr "Ungültiges Token zum Zurücksetzen des Passworts."
 

	
 
msgid "Successfully updated password"
 
msgstr "Erfolgreich Kennwort geändert"
 

	
 
msgid "Invalid reviewer \"%s\" specified"
 
msgstr "Ungültigen Begutachter \"%s\" angegeben"
 

	
 
msgid "%s (closed)"
 
msgstr "%s (geschlossen)"
 

	
 
msgid "Changeset"
 
msgstr "Änderungssatz"
 

	
 
msgid "Special"
 
msgstr "Spezial"
 

	
 
msgid "Peer branches"
 
msgstr "Branches anderer"
 

	
 
msgid "Bookmarks"
 
msgstr "Lesezeichen"
 

	
 
msgid "Error creating pull request: %s"
 
msgstr "Fehler beim Erstellen des Pull-Requests: %s"
 

	
 
msgid "Error occurred while creating pull request"
 
msgstr "Während des Erstellens des Pull Requests trat ein Fehler auf"
 

	
 
msgid "Successfully opened new pull request"
 
msgstr "Es wurde erfolgreich ein neuer Pullrequest eröffnet"
 

	
 
msgid "Meanwhile, the following reviewers have been added: %s"
 
msgstr "Es wurden inzwischen folgende Begutachter hinzugefügt: %s"
 

	
 
msgid "Meanwhile, the following reviewers have been removed: %s"
 
msgstr "Es wurden inzwischen folgende Begutachter entfernt: %s"
 

	
 
msgid "No description"
 
msgstr "Keine Beschreibung"
 

	
 
msgid "Pull request updated"
 
msgstr "Pull Request aktualisiert"
 

	
 
msgid "Successfully deleted pull request"
 
msgstr "Erfolgreich Pull-Request gelöscht"
 

	
 
msgid "Revision %s not found in %s"
 
msgstr "Die Revision %s konnte in %s nicht gefunden werden"
 

	
 
msgid "This pull request has already been merged to %s."
 
msgstr "Dieser Pull Request wurde bereits in %s integriert."
 

	
 
msgid "This pull request has been closed and can not be updated."
 
msgstr ""
 
"Dieser Pull Request wurde geschlossen und kann daher nicht aktualisiert "
 
"werden."
 

	
 
msgid "Note: Branch %s has another head: %s."
 
msgstr "Hinweis: Branch %s hat einen anderen Head: %s."
 

	
 
msgid "The diff can't be shown - the PR revisions could not be found."
 
msgstr ""
 
"Der diff kann nicht angezeigt werden. Die Pull Request Revisionen konnten "
 
"nicht gefunden werden."
 

	
 
msgid "Invalid search query. Try quoting it."
 
msgstr ""
 
"Ungültige Suchanfrage. Versuchen sie es in Anführungzeichen zu setzen."
 

	
 
msgid "The server has no search index."
 
msgstr "Der Server hat keinen Suchindex."
 

	
 
msgid "An error occurred during search operation."
 
msgstr "Während der Suchoperation trat ein Fehler auf."
 

	
 
msgid "No data ready yet"
 
msgstr "Es stehen noch keine Daten zur Verfügung"
 

	
 
msgid "Statistics are disabled for this repository"
 
msgstr "Statistiken sind deaktiviert für dieses Repository"
 

	
 
msgid "Auth settings updated successfully"
 
msgstr "Anmeldeeinstellungen erfolgreich geändert"
 

	
 
msgid "error occurred during update of auth settings"
 
msgstr "Fehler bei der Änderung der Anmeldeeinstellungen aufgetreten"
 

	
 
msgid "Default settings updated successfully"
 
msgstr "Standardeinstellungen erfolgreich geupdated"
 

	
 
msgid "Error occurred during update of defaults"
 
msgstr "Ein Fehler trat beim updaten der Standardeinstellungen auf"
 

	
 
msgid "Forever"
 
msgstr "Immer"
 

	
 
msgid "5 minutes"
 
msgstr "5 Minuten"
 

	
 
msgid "1 hour"
 
msgstr "1 Stunde"
 

	
 
msgid "1 day"
 
msgstr "1 Tag"
 

	
 
msgid "1 month"
 
msgstr "1 Monat"
 

	
 
msgid "Lifetime"
 
msgstr "Lebenszeit"
 

	
 
msgid "Error occurred during gist creation"
 
msgstr "Ein fehler trat auf bei der Erstellung des gist"
 

	
 
msgid "Deleted gist %s"
 
msgstr "gist %s gelöscht"
 

	
 
msgid "Unmodified"
 
msgstr "Ungeändert"
 

	
 
msgid "Successfully updated gist content"
 
msgstr "Erfolgreich Kerninhalt aktualisiert"
 

	
 
msgid "Successfully updated gist data"
 
msgstr "Erfolgreich Kerndaten aktualisiert"
 

	
 
msgid "Error occurred during update of gist %s"
 
msgstr "Fehler beim Aktualisieren der Kerndaten %s"
 

	
 
msgid "You can't edit this user since it's crucial for entire application"
 
msgstr ""
 
"Sie können diesen Benutzer nicht editieren, da er von entscheidender "
 
"Bedeutung für die ganze Applikation ist"
 

	
 
msgid "Your account was updated successfully"
 
msgstr "Ihr Konto wurde erfolgreich aktualisiert"
 

	
 
msgid "Error occurred during update of user %s"
 
msgstr "Fehler beim Aktualisieren der Benutzer %s"
 

	
 
msgid "Error occurred during update of user password"
 
msgstr "Fehler bei der Änderung des Kennworts"
 

	
 
msgid "Added email %s to user"
 
msgstr "Die E-Mail-Addresse %s wurde zum Benutzer hinzugefügt"
 

	
 
msgid "An error occurred during email saving"
 
msgstr "Währen der Speicherung der E-Mail-Addresse trat ein Fehler auf"
 

	
 
msgid "Removed email from user"
 
msgstr "Die E-Mail-Addresse wurde vom Benutzer entfernt"
 

	
 
msgid "API key successfully created"
 
msgstr "API Key wurde erfolgreich erstellt"
 

	
 
msgid "API key successfully reset"
 
msgstr "API-Schlüssel erfolgreich zurückgesetzt"
 

	
 
msgid "API key successfully deleted"
 
msgstr "API-Schlüssel erfolgreich gelöscht"
 

	
 
msgid "Read"
 
msgstr "Lesen"
 

	
 
msgid "Write"
 
msgstr "Schreiben"
 

	
 
msgid "Admin"
 
msgstr "Admin"
 

	
 
msgid "Disabled"
 
msgstr "Deaktiviert"
 

	
 
msgid "Allowed with manual account activation"
 
msgstr "Erlaubt mit manueller Kontoaktivierung"
 

	
 
msgid "Allowed with automatic account activation"
 
msgstr "Erlaubt mit automatischer Kontoaktivierung"
 

	
 
msgid "Manual activation of external account"
 
msgstr "Manuelle Aktivierung externen Kontos"
 

	
 
msgid "Automatic activation of external account"
 
msgstr "Automatische Aktivierung externen Kontos"
 

	
 
msgid "Enabled"
 
msgstr "Aktiviert"
 

	
 
msgid "Global permissions updated successfully"
 
msgstr "Globale Berechtigungen erfolgreich geändert"
 

	
 
msgid "Error occurred during update of permissions"
 
msgstr "Fehler bei der Änderung der globalen Berechtigungen"
 

	
 
msgid "Error occurred during creation of repository group %s"
 
msgstr "Fehler bei der Erstellung der Repositoriumsgruppe %s"
 

	
 
msgid "Created repository group %s"
 
msgstr "Repositoriumsgruppe %s erstellt"
 

	
 
msgid "Updated repository group %s"
 
msgstr "Repositoriumsgruppe %s aktualisiert"
 

	
 
msgid "Error occurred during update of repository group %s"
 
msgstr "Fehler bei der Aktualisierung der Repositoriumsgruppe %s"
 

	
 
msgid "This group contains %s repositories and cannot be deleted"
 
msgstr "Die Gruppe enthält %s Repositorys und kann nicht gelöscht werden"
 

	
 
msgid "This group contains %s subgroups and cannot be deleted"
 
msgstr "Diese Gruppe enthält %s Untergruppen und kann nicht gelöscht werden"
 

	
 
msgid "Removed repository group %s"
 
msgstr "Repositoriumsgruppe %s entfernt"
 

	
 
msgid "Error occurred during deletion of repository group %s"
 
msgstr "Fehler beim Löschen der Repositoriumsgruppe %s"
 

	
 
msgid "Cannot revoke permission for yourself as admin"
 
msgstr "Als Administrator kann man sich keine Berechtigungen entziehen"
 

	
 
msgid "Repository group permissions updated"
 
msgstr "Berechtigungen der Repositoriumsgruppe aktualisiert"
 

	
 
msgid "An error occurred during revoking of permission"
 
msgstr "Fehler beim Entzug der Berechtigungen"
 

	
 
msgid "Error creating repository %s"
 
msgstr "Fehler beim Erstellen des Repositoriums %s"
 

	
 
msgid "Created repository %s from %s"
 
msgstr "Repositorium %s von %s erstellt"
 

	
 
msgid "Forked repository %s as %s"
 
msgstr "Aufgespaltenes Repositorium %s zu %s"
 

	
 
msgid "Created repository %s"
 
msgstr "Repositorium erzeugt %s"
 

	
 
msgid "Repository %s updated successfully"
 
msgstr "Repository %s wurde erfolgreich aktualisiert"
 

	
 
msgid "Error occurred during update of repository %s"
 
msgstr "Fehler bei der Aktualisierung des Repositoriums %s"
 

	
 
msgid "Detached %s forks"
 
msgstr "%s Spaltung abgetrennt"
 

	
 
msgid "Deleted %s forks"
 
msgstr "%s Spaltung gelöscht"
 

	
 
msgid "Deleted repository %s"
 
msgstr "Repositorium %s gelöscht"
 

	
 
msgid "Cannot delete repository %s which still has forks"
 
msgstr "%s konnte nicht gelöscht werden, da es noch Forks besitzt"
 

	
 
msgid "An error occurred during deletion of %s"
 
msgstr "Beim Löschen von %s trat ein Fehler auf"
 

	
 
msgid "Repository permissions updated"
 
msgstr "Repositoriumsberechtigungen aktualisiert"
 

	
 
msgid "Field validation error: %s"
 
msgstr "Feldvalidierung fehlgeschlagen: %s"
 

	
 
msgid "An error occurred during removal of field"
 
msgstr "Fehler beim Entfernen des Feldes"
 

	
 
msgid "-- Not a fork --"
 
msgstr "-- Keine Abspaltung --"
 

	
 
msgid "Updated repository visibility in public journal"
 
msgstr "Sichtbarkeit des Repositorys im Öffentlichen Logbuch aktualisiert"
 

	
 
msgid "An error occurred during setting this repository in public journal"
 
msgstr ""
 
"Es trat ein Fehler während der Aktualisierung der Sicherbarkeit dieses "
 
"Repositorys im Öffentlichen Logbuch auf"
 

	
 
msgid "Nothing"
 
msgstr "Nichts"
 

	
 
msgid "Marked repository %s as fork of %s"
 
msgstr "Markiere Repository %s als Abzweig von Repository %s"
 

	
 
msgid "An error occurred during this operation"
 
msgstr "Während dieser operation trat ein Fehler auf"
 

	
 
msgid "Pulled from remote location"
 
msgstr "Von entferntem Ort übertragen"
 

	
 
msgid "An error occurred during pull from remote location"
 
msgstr ""
 
"Es trat ein Fehler auf während das Repository von einem Entfernten "
 
"Speicherort übertragen wurde"
 

	
 
msgid "An error occurred during deletion of repository stats"
 
msgstr "Während des löschens der Repository Statistiken trat ein Fehler auf"
 

	
 
msgid "Updated VCS settings"
 
msgstr "VCS-Einstellungen aktualisiert"
 

	
 
msgid "Error occurred while updating application settings"
 
msgstr ""
 
"Ein Fehler ist während der Aktualisierung der Applikationseinstellungen "
 
"aufgetreten"
 

	
 
msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 
msgstr ""
 
"Die Repositories wurden erfolgreich überprüft. Hinzugefügt: %s. Entfernt: "
 
"%s."
 

	
 
msgid "Updated application settings"
 
msgstr "Anwendungseinstellungen aktualisiert"
 

	
 
msgid "Updated visualisation settings"
 
msgstr "Visualisierungseinstellungen aktualisiert"
 

	
 
msgid "Error occurred during updating visualisation settings"
 
msgstr ""
 
"Es ist ein Fehler während der Aktualisierung der Layouteinstellung "
 
"aufgetreten"
 

	
 
msgid "Please enter email address"
 
msgstr "Bitte geben Sie eine E-Mail-Adresse an"
 

	
 
msgid "Send email task created"
 
msgstr "Task zum Versenden von E-Mails erstellt"
 

	
 
msgid "Builtin hooks are read-only. Please use another hook name."
 
msgstr ""
 
"Die eingebauten Hooks sind schreibgeschützt. Bitte verwenden Sie einen "
 
"anderen Hook-Namen."
 

	
 
msgid "Added new hook"
 
msgstr "Neuer Hook hinzugefügt"
 

	
 
msgid "Updated hooks"
 
msgstr "Die Hooks wurden aktutalisiert"
 

	
 
msgid "Error occurred during hook creation"
 
msgstr "Während der Erzeugung des Hooks ist ein Fehler aufgetreten"
 

	
 
msgid "Whoosh reindex task scheduled"
 
msgstr "Whoosh Reindizierungs Aufgabe wurde zur Ausführung geplant"
 

	
 
msgid "Created user group %s"
 
msgstr "Nutzergruppe %s erstellt"
 

	
 
msgid "Error occurred during creation of user group %s"
 
msgstr ""
 
"Es ist ein Fehler während der Erstellung der Nutzergruppe %s aufgetreten"
 

	
 
msgid "Updated user group %s"
 
msgstr "Aktualisierte Nutzergruppe %s"
 

	
 
msgid "Error occurred during update of user group %s"
 
msgstr ""
 
"Während des Updates der Benutzergruppe %s ist ein Fehler aufgetreten"
 

	
 
msgid "Successfully deleted user group"
 
msgstr "Die Nutzergruppe wurde erfolgreich entfernt"
 

	
 
msgid "An error occurred during deletion of user group"
 
msgstr "Während des Löschens der Benutzergruppe ist ein Fehler aufgetreten"
 

	
 
msgid "Target group cannot be the same"
 
msgstr "Zielgruppe kann nicht die gleiche Gruppe sein"
 

	
 
msgid "User group permissions updated"
 
msgstr "Berechtigungen der Benutzergruppe wurden aktualisiert"
 

	
 
msgid "Updated permissions"
 
msgstr "Berechtigungen wurden aktualisiert"
 

	
 
msgid "An error occurred during permissions saving"
 
msgstr ""
 
"Es ist ein Fehler während des Speicherns der Berechtigungen aufgetreten"
 

	
 
msgid "Created user %s"
 
msgstr "Nutzer %s erstellt"
 

	
 
msgid "Error occurred during creation of user %s"
 
msgstr "Während des Erstellens des Benutzers %s ist ein Fehler aufgetreten"
 

	
 
msgid "User updated successfully"
 
msgstr "Der Benutzer wurde erfolgreich aktualisiert"
 

	
 
msgid "Successfully deleted user"
 
msgstr "Der Nutzer wurde erfolgreich gelöscht"
 

	
 
msgid "An error occurred during deletion of user"
 
msgstr "Während der Löschen des Benutzers trat ein Fehler auf"
 

	
 
msgid "The default user cannot be edited"
 
msgstr "Der Standard-Benutzer kann nicht bearbeitet werden"
 

	
 
msgid "Added IP address %s to user whitelist"
 
msgstr "Die IP-Adresse %s wurde zur Nutzerwhitelist hinzugefügt"
 

	
 
msgid "An error occurred while adding IP address"
 
msgstr "Während des Speicherns der IP-Adresse ist ein Fehler aufgetreten"
 

	
 
msgid "Removed IP address from user whitelist"
 
msgstr "IP-Adresse wurde von der Nutzerwhitelist entfernt"
 

	
 
msgid "You need to be a registered user to perform this action"
 
msgstr ""
 
"Sie müssen ein Registrierter Nutzer sein um diese Aktion durchzuführen"
 

	
 
msgid "You need to be signed in to view this page"
 
msgstr "Sie müssen sich anmelden um diese Seite aufzurufen"
 

	
 
msgid ""
 
"CSRF token leak has been detected - all form tokens have been expired"
 
msgstr ""
 
"Es wurde ein CSRF Leck entdeckt. Alle Formular Token sind abgelaufen"
 

	
 
msgid "Repository not found in the filesystem"
 
msgstr "Das Repository konnte nicht im Filesystem gefunden werden"
 

	
 
msgid "Binary file"
 
msgstr "Binäre Datei"
 

	
 
msgid ""
 
"Changeset was too big and was cut off, use diff menu to display this diff"
 
msgstr ""
 
"Der Änderungssatz war zu groß und wurde abgeschnitten, benutzen sie das "
 
"Diff Menü um die Unterschiede anzuzeigen"
 

	
 
msgid "No changes detected"
 
msgstr "Keine Änderungen erkannt"
 

	
 
msgid "Deleted branch: %s"
 
msgstr "Branch %s gelöscht"
 

	
 
msgid "Created tag: %s"
 
msgstr "Tag %s erstellt"
 

	
 
msgid "Show all combined changesets %s->%s"
 
msgstr "Zeige alle Kombinierten Änderungensätze %s->%s"
 

	
 
msgid "Compare view"
 
msgstr "Vergleichsansicht"
 

	
 
msgid "and"
 
msgstr "und"
 

	
 
msgid "%s more"
 
msgstr "%s mehr"
 

	
 
msgid "revisions"
 
msgstr "revisionen"
 

	
 
msgid "Fork name %s"
 
msgstr "Fork Name %s"
 

	
 
msgid "Pull request %s"
 
msgstr "Pull Request %s"
 

	
 
msgid "[deleted] repository"
 
msgstr "[gelöscht] Repository"
 

	
 
msgid "[created] repository"
 
msgstr "[erstellt] Repository"
 

	
 
msgid "[created] repository as fork"
 
msgstr "[erstellt] Repository als Fork"
 

	
 
msgid "[forked] repository"
 
msgstr "[forked] Repository"
 

	
 
msgid "[updated] repository"
 
msgstr "[aktualisiert] Repository"
 

	
 
msgid "[downloaded] archive from repository"
 
msgstr "Archiv von Repository [heruntergeladen]"
 

	
 
msgid "[delete] repository"
 
msgstr "Repository [gelöscht]"
 

	
 
msgid "[created] user"
 
msgstr "Benutzer [erstellt]"
 

	
 
msgid "[updated] user"
 
msgstr "Benutzer [akutalisiert]"
 

	
 
msgid "[created] user group"
 
msgstr "Benutzergruppe [erstellt]"
 

	
 
msgid "[updated] user group"
 
msgstr "Benutzergruppe [aktualisiert]"
 

	
 
msgid "[commented] on revision in repository"
 
msgstr "Revision [kommentiert] in Repository"
 

	
 
msgid "[commented] on pull request for"
 
msgstr "Pull Request [kommentiert] für"
 

	
 
msgid "[closed] pull request for"
 
msgstr "Pull Request [geschlossen] für"
 

	
 
msgid "[pushed] into"
 
msgstr "[Pushed] in"
 

	
 
msgid "[committed via Kallithea] into repository"
 
msgstr "[via Kallithea] in Repository [committed]"
 

	
 
msgid "[pulled from remote] into repository"
 
msgstr "[Pulled von Remote] in Repository"
 

	
 
msgid "[pulled] from"
 
msgstr "[Pulled] von"
 

	
 
msgid "[started following] repository"
 
msgstr "[Following gestartet] für Repository"
 

	
 
msgid "[stopped following] repository"
 
msgstr "[Following gestoppt] für Repository"
 

	
 
msgid " and %s more"
 
msgstr " und %s weitere"
 

	
 
msgid "No files"
 
msgstr "Keine Dateien"
 

	
 
msgid "new file"
 
msgstr "neue Datei"
 

	
 
msgid "mod"
 
msgstr "mod"
 

	
 
msgid "del"
 
msgstr "entf"
 

	
 
msgid "rename"
 
msgstr "umbenennen"
 

	
 
msgid "chmod"
 
msgstr "chmod"
 

	
 
msgid ""
 
"%s repository is not mapped to db perhaps it was created or renamed from "
 
"the filesystem please run the application again in order to rescan "
 
"repositories"
 
msgstr ""
 
"Das %s Repository ist nicht in der Datenbank vorhanden, eventuell wurde "
 
"es im Dateisystem erstellt oder umbenannt. Bitte starten sie die "
 
"Applikation erneut um die Repositories neu zu Indizieren"
 

	
 
msgid "%d year"
 
msgid_plural "%d years"
 
msgstr[0] "%d Jahr"
 
msgstr[1] "%d Jahre"
 

	
 
msgid "%d month"
 
msgid_plural "%d months"
 
msgstr[0] "%d Monat"
 
msgstr[1] "%d Monate"
 

	
 
msgid "%d day"
 
msgid_plural "%d days"
 
msgstr[0] "%d Tag"
 
msgstr[1] "%d Tage"
 

	
 
msgid "%d hour"
 
msgid_plural "%d hours"
 
msgstr[0] "%d Stunde"
 
msgstr[1] "%d Stunden"
 

	
 
msgid "%d minute"
 
msgid_plural "%d minutes"
 
msgstr[0] "%d Minute"
 
msgstr[1] "%d Minuten"
 

	
 
msgid "%d second"
 
msgid_plural "%d seconds"
 
msgstr[0] "%d Sekunde"
 
msgstr[1] "%d Sekunden"
 

	
 
msgid "in %s"
 
msgstr "in %s"
 

	
 
msgid "%s ago"
 
msgstr "vor %s"
 

	
 
msgid "in %s and %s"
 
msgstr "in %s und %s"
 

	
 
msgid "%s and %s ago"
 
msgstr "%s und %s her"
 

	
 
msgid "just now"
 
msgstr "jetzt gerade"
 

	
 
msgid "on line %s"
 
msgstr "in Zeile %s"
 

	
 
msgid "[Mention]"
 
msgstr "[Mention]"
 

	
 
msgid "top level"
 
msgstr "höchste Ebene"
 

	
 
msgid "Kallithea Administrator"
 
msgstr "Kallithea Administrator"
 

	
 
msgid "Default user has no access to new repositories"
 
msgstr "Der Standard-Benutzer hat keinen Zugriff auf neue Repositories"
 

	
 
msgid "Default user has read access to new repositories"
 
msgstr "Der Standard-Benutzer hat Leserechte auf neuen Repositories"
 

	
 
msgid "Default user has write access to new repositories"
 
msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Repositories"
 

	
 
msgid "Default user has admin access to new repositories"
 
msgstr "Der Standard-Benutzer hat Admin-Rechte auf neuen Repositories"
 

	
 
msgid "Default user has no access to new repository groups"
 
msgstr ""
 
"Der Standard-Benutzer hat keinen Zugriff auf neue Repository-Gruppen"
 

	
 
msgid "Default user has read access to new repository groups"
 
msgstr "Der Standard-Benutzer hat Leserechte auf neuen Repository-Gruppen"
 

	
 
msgid "Default user has write access to new repository groups"
 
msgstr "Der Standard-Benutzer Schreibrechte auf neuen Repository-Gruppen"
 

	
 
msgid "Default user has admin access to new repository groups"
 
msgstr "Der Standard-Benutzer Admin-Rechte 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"
 

	
 
msgid "Default user has read access to new user groups"
 
msgstr "Der Standard-Benutzer hat Leserechte auf neuen Benutzer-Gruppen"
 

	
 
msgid "Default user has write access to new user groups"
 
msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Benutzer-Gruppen"
 

	
 
msgid "Default user has admin access to new user groups"
 
msgstr "Der Standard-Benutzer hat Admin-Rechte auf neuen Benutzer-Gruppen"
 

	
 
msgid "Only admins can create repository groups"
 
msgstr "Nur Admins können Repository-Gruppen erstellen"
 

	
 
msgid "Non-admins can create repository groups"
 
msgstr "Nicht-Admins können Repository-Gruppen erstellen"
 

	
 
msgid "Only admins can create user groups"
 
msgstr "Nur Admins können Benutzer-Gruppen erstellen"
 

	
 
msgid "Non-admins can create user groups"
 
msgstr "Nicht-Admins können Benutzer-Gruppen erstellen"
 

	
 
msgid "Only admins can create top level repositories"
 
msgstr "Nur Admins können Repositories auf oberster Ebene erstellen"
 

	
 
msgid "Non-admins can create top level repositories"
 
msgstr "Nicht-Admins können Repositories oberster Ebene erstellen"
 

	
 
msgid ""
 
"Repository creation enabled with write permission to a repository group"
 
msgstr ""
 
"Erstellung von Repositories mit Schreibzugriff für Repositorygruppe "
 
"aktiviert"
 

	
 
msgid ""
 
"Repository creation disabled with write permission to a repository group"
 
msgstr ""
 
"Erstellung von Repositories mit Schreibzugriff für Repositorygruppe "
 
"deaktiviert"
 

	
 
msgid "Only admins can fork repositories"
 
msgstr "Nur Admins können Repositories forken"
 

	
 
msgid "Non-admins can fork repositories"
 
msgstr "Nicht-Admins können Repositorys forken"
 

	
 
msgid "Registration disabled"
 
msgstr "Registrierung deaktiviert"
 

	
 
msgid "User registration with manual account activation"
 
msgstr "Benutzerregistrierung mit manueller Kontoaktivierung"
 

	
 
msgid "User registration with automatic account activation"
 
msgstr "Benutzerregistrierung mit automatischer Kontoaktivierung"
 

	
 
msgid "Not reviewed"
 
msgstr "Nicht Begutachtet"
 

	
 
msgid "Under review"
 
msgstr "In Begutachtung"
 

	
 
msgid "Approved"
 
msgstr "Akzeptiert"
 

	
 
msgid "Please enter a login"
 
msgstr "Bitte einen Benutzernamen eingeben"
 

	
 
msgid "Enter a value %(min)i characters long or more"
 
msgstr "Bitte einen Wert mit mindestens %(min)i Zeichen eingeben"
 

	
 
msgid "Please enter a password"
 
msgstr "Bitte ein Passwort eingeben"
 

	
 
msgid "Enter %(min)i characters or more"
 
msgstr "Bitte mindestens %(min)i Zeichen eingeben"
 

	
 
msgid "Name must not contain only digits"
 
msgstr "Name darf nicht nur Ziffern enthalten"
 

	
 
msgid "New user %(new_username)s registered"
 
msgstr "Neuer Benutzer %(new_username)s registriert"
 

	
 
msgid "Closing"
 
msgstr "Schließen"
 

	
 
msgid ""
 
"Cannot create pull request - criss cross merge detected, please merge a "
 
"later %s revision to %s"
 
msgstr ""
 
"Pull-Request kann nicht erstellt werden - Criss Cross Merge erkannt, "
 
"bitte eine spätere %s-Revision in %s zusammenführen."
 

	
 
msgid "You are not authorized to create the pull request"
 
msgstr "Sie sind nicht berechtigt, den Pull-Request anzulegen."
 

	
 
msgid "Closed, next iteration: %s ."
 
msgstr "Geschlossen, nächste Iteration: %s ."
 

	
 
msgid "latest tip"
 
msgstr "Letzter Tip"
 

	
 
msgid "New user registration"
 
msgstr "Neue Benutzerregistrierung"
 

	
 
msgid ""
 
"User \"%s\" still owns %s repositories and cannot be removed. Switch "
 
"owners or remove those repositories: %s"
 
msgstr ""
 
"Der Benutzer \"%s\" besitzt noch immer %s Repositories und kann daher "
 
"nicht entfernt werden. Entweder muss der Besitzer geändert oder das "
 
"Repository entfernt werden: %s"
 

	
 
msgid ""
 
"User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 
"owners or remove those repository groups: %s"
 
msgstr ""
 
"Der Benutzer \"%s\" ist noch der Besitzer von %s Repositorygruppen und "
 
"kann daher nicht entfernt werden. Entweder muss der Besitzer geändert "
 
"oder die Repositorygruppen müssen entfernt werden: %s"
 

	
 
msgid ""
 
"User \"%s\" still owns %s user groups and cannot be removed. Switch "
 
"owners or remove those user groups: %s"
 
msgstr ""
 
"Der Benutzer \"%s\" besitzt noch immer %s Benutzergruppen und kann daher "
 
"nicht entfernt werden. Entweder muss der Besitzer geändert oder die "
 
"Benutzergruppen müssen gelöscht werden: %s"
 

	
 
msgid "Password reset link"
 
msgstr "Link zum Zurücksetzen des Passworts"
 

	
 
msgid ""
 
"The password to your account %s has been changed using password reset "
 
"form."
 
msgstr ""
 
"Das Passwort für dein Konto %s wurde mit dem Formular zum Zurücksetzen "
 
"des Passworts geändert."
 

	
 
msgid "Value cannot be an empty list"
 
msgstr "Eine leere Liste ist kein gültiger Wert"
 

	
 
msgid "Username \"%(username)s\" already exists"
 
msgstr "Benutezrname \"%(username)s\" existiert bereits"
 

	
 
msgid "The input is not valid"
 
msgstr "Die Eingabe ist nicht gültig"
 

	
 
msgid "Username %(username)s is not valid"
 
msgstr "Benutzername \"%(username)s\" ist ungültig"
 

	
 
msgid "Invalid user group name"
 
msgstr "Ungültiger Benutzergruppenname"
 

	
 
msgid "User group \"%(usergroup)s\" already exists"
 
msgstr "Benutzergruppe \"%(usergroup)s\" existiert bereits"
 

	
 
msgid ""
 
"user group name may only contain alphanumeric characters underscores, "
 
"periods or dashes and must begin with alphanumeric character"
 
msgstr ""
 
"Der Name einer Benutzergruppe darf nur alphanumerische Zeichen, "
 
"Unterstriche, Punkte oder Bindestriche enthalten und muss mit einem "
 
"alphanumerischen Zeichen beginnen"
 

	
 
msgid "Cannot assign this group as parent"
 
msgstr "Kann diese Gruppe nicht als vorgesetzt setzen"
 

	
 
msgid "Group \"%(group_name)s\" already exists"
 
msgstr "Gruppe \"%(group_name)s\" existiert bereits"
 

	
 
msgid "Repository with name \"%(group_name)s\" already exists"
 
msgstr "Es gibt bereits ein Repository mit \"%(group_name)s\""
 

	
 
msgid "Invalid characters (non-ascii) in password"
 
msgstr "Üngültige(nicht ASCII) Zeichen im Passwort"
 

	
 
msgid "Invalid old password"
 
msgstr "Ungültiges altes Passwort"
 

	
 
msgid "Passwords do not match"
 
msgstr "Die Passwörter stimmen nicht überein"
 

	
 
msgid "Repository named %(repo)s already exists"
 
msgstr "Es gibt bereits ein Repository mit \"%(repo)s\""
 

	
 
msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 
msgstr ""
 
"Es gibt bereits ein Repository mit \"%(repo)s\" in der Gruppe \"%(group)s"
 
"\""
 

	
 
msgid "Repository group with name \"%(repo)s\" already exists"
 
msgstr "Eine Repositorygruppe mit dem Namen \"%(repo)s\" existiert bereits"
 

	
 
msgid "Invalid repository URL"
 
msgstr "Ungültige Repository-URL"
 

	
 
msgid "Fork has to be the same type as parent"
 
msgstr "Forke um den selben typ wie der Vorgesetze zu haben"
 

	
 
msgid "You don't have permissions to create repository in this group"
 
msgstr ""
 
"Du hast nicht die erforderlichen Berechtigungen, um in dieser Gruppe ein "
 
"Repository zu erzeugen"
 

	
 
msgid "no permission to create repository in root location"
 
msgstr "keine Berechtigung, um ein Repository auf höchster Ebene anzulegen"
 

	
 
msgid "You don't have permissions to create a group in this location"
 
msgstr ""
 
"Sie haben keine Berechtigung, um an diesem Ort ein Repository anzulegen"
 

	
 
msgid "This username or user group name is not valid"
 
msgstr "Dieser Benutzername oder Benutzergruppenname ist nicht gültig"
 

	
 
msgid "This is not a valid path"
 
msgstr "Dies ist ein Ungültiger Pfad"
 

	
 
msgid "This email address is already in use"
 
msgstr "Diese E-Mail-Addresse ist bereits in Benutzung"
 

	
 
msgid "Email address \"%(email)s\" not found"
 
msgstr "E-Mail-Addresse „%(email)s“ existiert nicht."
 

	
 
msgid ""
 
"The LDAP Login attribute of the CN must be specified - this is the name "
 
"of the attribute that is equivalent to \"username\""
 
msgstr ""
 
"Das LDAP-Login-Attribut des CN muss angeben werden - Es ist der Name des "
 
"Attributes äquivalent zu \"Benutzername\""
 

	
 
msgid "Please enter a valid IPv4 or IPv6 address"
 
msgstr "Bitte eine gültige IPv4- oder IPv6-Adresse angeben"
 

	
 
msgid ""
 
"The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 
msgstr ""
 
"Die Größe (in Bits) des Netzwerks muss im Bereich 0-32 liegen (nicht "
 
"%(bits)r)"
 

	
 
msgid "Key name can only consist of letters, underscore, dash or numbers"
 
msgstr ""
 
"Der Name eines Schlüssels darf nur aus Buchstaben, Ziffern, Unterstrich "
 
"und Bindestrich bestehen"
 

	
 
msgid "Filename cannot be inside a directory"
 
msgstr "Dateiname darf kein Unterverzeichnis enthalten"
 

	
 
msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 
msgstr ""
 
"Die Plug-Ins %(loaded)s und %(next_to_load)s exportieren beide den selben "
 
"Namen"
 

	
 
msgid "About"
 
msgstr "Über"
 

	
 
msgid "Add Repository"
 
msgstr "Repository hinzufügen"
 

	
 
msgid "Add Repository Group"
 
msgstr "Repositorygruppe hinzufügen"
 

	
 
msgid "You have admin right to this group, and can edit it"
 
msgstr "Du hast Adminrechte für diese Gruppe und kannst sie editieren"
 

	
 
msgid "Edit Repository Group"
 
msgstr "Repositorygruppe bearbeiten"
 

	
 
msgid "Repository"
 
msgstr "Repository"
 

	
 
msgid "Description"
 
msgstr "Beschreibung"
 

	
 
msgid "Last Change"
 
msgstr "Letzte Änderung"
 

	
 
msgid "Tip"
 
msgstr "Tipp"
 

	
 
msgid "Owner"
 
msgstr "Besitzer"
 

	
 
msgid "Log In"
 
msgstr "Log In"
 

	
 
msgid "Log In to %s"
 
msgstr "Log In in %s"
 

	
 
msgid "Username"
 
msgstr "Benutzername"
 

	
 
msgid "Password"
 
msgstr "Passwort"
 

	
 
msgid "Stay logged in after browser restart"
 
msgstr "Nach dem Neustart des Browsers eingeloggt bleiben"
 

	
 
msgid "Forgot your password ?"
 
msgstr "Passowrt Vergessen?"
 

	
 
msgid "Don't have an account ?"
 
msgstr "Kein Account?"
 

	
 
msgid "Sign In"
 
msgstr "Einloggen"
 

	
 
msgid "Password Reset"
 
msgstr "Passwort zurücksetzen"
 

	
 
msgid "Reset Your Password to %s"
 
msgstr "Setze dein Passwort auf %s zurück"
 

	
 
msgid "Reset Your Password"
 
msgstr "Setze dein Passwort zurück"
 

	
 
msgid "Email Address"
 
msgstr "E-Mail-Adresse"
 

	
 
msgid "Captcha"
 
msgstr "CAPTCHA"
 

	
 
msgid "Send Password Reset Email"
 
msgstr "E-Mail zum Zurücksetzen des Passworts anfordern"
 

	
 
msgid ""
 
"A password reset link will be sent to the specified email address if it "
 
"is registered in the system."
 
msgstr ""
 
"Ein Link zum Zurücksetzen des Passworts wird an die angegebene E-Mail-"
 
"Adresse gesendet, wenn diese im System registriert ist."
 

	
 
msgid "You are about to set a new password for the email address %s."
 
msgstr ""
 
"Du bist dabei, ein neues Passwort für die E-Mail-Adresse %s festzulegen."
 

	
 
msgid ""
 
"Note that you must use the same browser session for this as the one used "
 
"to request the password reset."
 
msgstr ""
 
"Beachten Sie, dass Sie dafür die gleiche Browsersitzung verwenden müssen, "
 
"mit der Sie das Zurücksetzen des Passworts beantragt haben."
 

	
 
msgid "Code you received in the email"
 
msgstr "Code, den du in der E-Mail erhalten hast"
 

	
 
msgid "Confirm"
 
msgstr "Bestätigen"
 

	
 
msgid "Sign Up"
 
msgstr "Registrieren"
 

	
 
msgid "Sign Up to %s"
 
msgstr "Registrieren für %s"
 

	
 
msgid "Re-enter password"
 
msgstr "Passwort erneut eingeben"
 

	
 
msgid "First Name"
 
msgstr "Vorname"
 

	
 
msgid "Last Name"
 
msgstr "Nachname"
 

	
 
msgid "Email"
 
msgstr "E-Mail"
 

	
 
msgid "Registered accounts are ready to use and need no further action."
 
msgstr "Registrierte Konten können ohne weitere Aktion genutzt werden."
 

	
 
msgid "Please wait for an administrator to activate your account."
 
msgstr ""
 
"Bitte warten Sie auf die Aktivierung Ihres Benutzerkontos durch einen "
 
"Administrator."
 

	
 
msgid "Admin Journal"
 
msgstr "Admin-Logbuch"
 

	
 
msgid "journal filter..."
 
msgstr "Logbuch filter..."
 

	
 
msgid "Filter"
 
msgstr "Filter"
 

	
 
msgid "%s Entry"
 
msgid_plural "%s Entries"
 
msgstr[0] "%s Eintrag"
 
msgstr[1] "%s Einträge"
 

	
 
msgid "Action"
 
msgstr "Aktion"
 

	
 
msgid "Date"
 
msgstr "Datum"
 

	
 
msgid "From IP"
 
msgstr "Von IP"
 

	
 
msgid "No actions yet"
 
msgstr "Es sind bisher keine Aktionen passiert"
 

	
 
msgid "Authentication Settings"
 
msgstr "Authentifizierungseinstellungen"
 

	
 
msgid "Authentication"
 
msgstr "Authentifizierung"
 

	
 
msgid "Authentication Plugins"
 
msgstr "Plug-Ins zur Authentifizierung"
 

	
 
msgid "Enabled Plugins"
 
msgstr "Aktivierte Plugins"
 

	
 
msgid "Available built-in plugins"
 
msgstr "Verfügbare mitgelieferte Plug-Ins"
 

	
 
msgid "Plugin"
 
msgstr "Plugin"
 

	
 
msgid "Save"
 
msgstr "Speichern"
 

	
 
msgid "Repository Defaults"
 
msgstr "Repositorystandards"
 

	
 
msgid "Type"
 
msgstr "Typ"
 

	
 
msgid "Private repository"
 
msgstr "Privates Repository"
 

	
 
msgid ""
 
"Private repositories are only visible to people explicitly added as "
 
"collaborators."
 
msgstr ""
 
"Private Repositories sind nur für explizit hinzugefügte Mitarbeiter "
 
"sichtbar."
 

	
 
msgid "Enable statistics"
 
msgstr "Aktiviere Statistiken"
 

	
 
msgid "Enable statistics window on summary page."
 
msgstr "Statistik-Fenster in der Zusammenfassungsseite aktivieren."
 

	
 
msgid "Enable downloads"
 
msgstr "Aktiviere Downloads"
 

	
 
msgid "Enable download menu on summary page."
 
msgstr "Download-Menü auf der Zusammenfassungsseite aktivieren."
 

	
 
msgid "Edit Gist"
 
msgstr "Gist editieren"
 

	
 
msgid ""
 
"Gist was updated since you started editing. Copy your changes and click "
 
"%(here)s to reload new version."
 
msgstr ""
 
"Gist wurde während der Änderung aktualisiert. Änderungen kopieren und "
 
"%(here)s klicken um die neue Version nachzuladen."
 

	
 
msgid "here"
 
msgstr "hier"
 

	
 
msgid "Gist description ..."
 
msgstr "Gist Beschreibung ..."
 

	
 
msgid "Gist lifetime"
 
msgstr "Gist Lebenszeit"
 

	
 
msgid "Expires"
 
msgstr "Verfällt"
 

	
 
msgid "Update Gist"
 
msgstr "Gist aktualisieren"
 

	
 
msgid "Cancel"
 
msgstr "Abbrechen"
 

	
 
msgid "Private Gists for User %s"
 
msgstr "Privater Gist für Benutzer %s"
 

	
 
msgid "Public Gists for User %s"
 
msgstr "Öffentlicher Gist für Benutzer %s"
 

	
 
msgid "Public Gists"
 
msgstr "Öffentliche Gists"
 

	
 
msgid "Create New Gist"
 
msgstr "Neuen Gist erstellen"
 

	
 
msgid "Created"
 
msgstr "Erstellt"
 

	
 
msgid "There are no gists yet"
 
msgstr "Bisher sind keine Gists vorhanden"
 

	
 
msgid "New Gist"
 
msgstr "Neuer Gist"
 

	
 
msgid "Create Private Gist"
 
msgstr "Privaten Gist erstellen"
 

	
 
msgid "Create Public Gist"
 
msgstr "Öffentlichen Gist erstellen"
 

	
 
msgid "Reset"
 
msgstr "Zurücksetzen"
 

	
 
msgid "Gist"
 
msgstr "Gist"
 

	
 
msgid "URL"
 
msgstr "URL"
 

	
 
msgid "Public Gist"
 
msgstr "Öffentlicher Gist"
 

	
 
msgid "Private Gist"
 
msgstr "Privater Gist"
 

	
 
msgid "Delete"
 
msgstr "Löschen"
 

	
 
msgid "Confirm to delete this Gist"
 
msgstr "Löschen des Gists bestätigen"
 

	
 
msgid "Edit"
 
msgstr "Bearbeiten"
 

	
 
msgid "Show as Raw"
 
msgstr "Als Raw anzeigen"
 

	
 
msgid "created"
 
msgstr "erstellt"
 

	
 
msgid "Show as raw"
 
msgstr "Als Raw anzeigen"
 

	
 
msgid "My Account"
 
msgstr "Mein Account"
 

	
 
msgid "Profile"
 
msgstr "Profil"
 

	
 
msgid "Email Addresses"
 
msgstr "E-Mail-Adressen"
 

	
 
msgid "API Keys"
 
msgstr "API Keys"
 

	
 
msgid "Owned Repositories"
 
msgstr "Eigene Repositories"
 

	
 
msgid "Watched Repositories"
 
msgstr "Beobachtete Repositories"
 

	
 
msgid "Show Permissions"
 
msgstr "Berechtigungen anzeigen"
 

	
 
msgid "Built-in"
 
msgstr "Mitgeliefert"
 

	
 
msgid "Confirm to reset this API key: %s"
 
msgstr "Zurücksetzen des API-Schlüssels \"%s\" bestätigen"
 

	
 
msgid "Expired"
 
msgstr "Verfallen"
 

	
 
msgid "Confirm to remove this API key: %s"
 
msgstr "Entfernen des API-Schlüssels \"%s\" bestätigen"
 

	
 
msgid "Remove"
 
msgstr "Entfernen"
 

	
 
msgid "No additional API keys specified"
 
msgstr "Keine weiteren API-Schlüssel angegeben"
 

	
 
msgid "New API key"
 
msgstr "Neuer API-Schlüssel"
 

	
 
msgid "Add"
 
msgstr "Hinzufügen"
 

	
 
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 ""
 
"\n"
 
"API-Schlüssel werden verwendet, um Skripten oder Diensten denselben\n"
 
"Zugang zu %s zu gewähren, den Sie mit Eingabe Ihres Passworts\n"
 
"erlangen würden.\n"
 

	
 
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 ""
 
"\n"
 
"Ebenso wie Passworte, sollten API-Schlüssel somit niemals mit anderen\n"
 
"geteilt oder von nicht-vertrauenswürdigen Skripten oder Diensten\n"
 
"verwendet werden. Falls ein solcher Zugriff zwischenzeitlich passiert "
 
"sein\n"
 
"sollte, dann können Sie hier den API-Schlüssel zurücksetzen, um weiteren\n"
 
"Missbrauchen zu verhindern.\n"
 

	
 
msgid "Primary"
 
msgstr "Primär"
 

	
 
msgid "Confirm to delete this email: %s"
 
msgstr "Löschen der E-Mail „%s“ bestätigen"
 

	
 
msgid "No additional emails specified."
 
msgstr "Keine weiteren E-Mails spezifiziert."
 

	
 
msgid "New email address"
 
msgstr "Neue E-Mailadresse"
 

	
 
msgid "Change Your Account Password"
 
msgstr "Passwort des Benutzerkontos ändern"
 

	
 
msgid "Current password"
 
msgstr "Aktuelles Passwort"
 

	
 
msgid "New password"
 
msgstr "Neues Passwort"
 

	
 
msgid "Confirm new password"
 
msgstr "Bestätige neues Passwort"
 

	
 
msgid ""
 
"This account is managed with %s and the password cannot be changed here"
 
msgstr ""
 
"Dieser Account wird mit %s verwaltet - daher kann das Passwort nicht "
 
"geändert werden"
 

	
 
msgid "Gravatar"
 
msgstr "Gravatar"
 

	
 
msgid "Change %s avatar at"
 
msgstr "Benutzerbild %s ändern unter"
 

	
 
msgid "Avatars are disabled"
 
msgstr "Avatare sind deaktiviert"
 

	
 
msgid "Repositories You Own"
 
msgstr "Repositories in Ihrem Besitz"
 

	
 
msgid "Name"
 
msgstr "Name"
 

	
 
msgid "Repositories You are Watching"
 
msgstr "Repositories, denen Sie folgen"
 

	
 
msgid "Default Permissions"
 
msgstr "Standardrechte"
 

	
 
msgid "Global"
 
msgstr "Global"
 

	
 
msgid "IP Whitelist"
 
msgstr "IP Whitelist"
 

	
 
msgid "Anonymous access"
 
msgstr "Anonymer Zugang"
 

	
 
msgid ""
 
"Allow access to Kallithea without needing to log in. Anonymous users use "
 
"%s user permissions."
 
msgstr ""
 
"Unauthentifizierten Zugriff auf Kallithea erlauben. Anonyme Benutzer "
 
"verwenden %s Benutzerrechte."
 

	
 
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 ""
 
"Alle Standardrechte jedes Repositorys werden auf die gewählten Rechte "
 
"gesetzt. Beachten Sie, dass alle spezifischen Standardrechte der "
 
"Repositories verloren gehen"
 

	
 
msgid "Apply to all existing repositories"
 
msgstr "Auf alle bestehenden Repositories anwenden"
 

	
 
msgid "Permissions for the Default user on new repositories."
 
msgstr "Berechtigungen für neue Repositories des Vorgabe-Benutzers."
 

	
 
msgid "Repository group"
 
msgstr "Repository Gruppe"
 

	
 
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 ""
 
"Alle Standardrechte jeder Repositorygruppe werden auf die gewählten "
 
"Rechte gesetzt. Beachten Sie, dass all spezifischen Standardrechte der "
 
"Repositorygruppen verloren gehen"
 

	
 
msgid "Apply to all existing repository groups"
 
msgstr "Auf alle bestehenden Repository-Gruppen anwenden"
 

	
 
msgid "Permissions for the Default user on new repository groups."
 
msgstr "Berechtigungen des Vorgabe-Benutzers für neue Repository-Gruppen."
 

	
 
msgid "User group"
 
msgstr "Benutzergruppe"
 

	
 
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 ""
 
"Alle Vorgabe-Berechtigungen jeder Benutzergruppe werden auf die gewählten "
 
"Berechtigungen zurückgesetzt. Beachten Sie, dass dabei alle Anpassungen "
 
"von Vorgabe-Berechtigungen für Benutzergruppen verloren gehen"
 

	
 
msgid "Apply to all existing user groups"
 
msgstr "Auf alle bestehenden Benutzergruppen anwenden"
 

	
 
msgid "Permissions for the Default user on new user groups."
 
msgstr "Berechtigungen für neue Benutzergruppen des den Vorgabe-Benutzer."
 

	
 
msgid "Top level repository creation"
 
msgstr "Erstellung eines übergeordneten Repositories"
 

	
 
msgid ""
 
"Enable this to allow non-admins to create repositories at the top level."
 
msgstr ""
 
"Aktiviere dies, damit Nicht-Administratoren Repositories auf der obersten "
 
"Ebene erstellen können."
 

	
 
msgid ""
 
"Note: This will also give all users API access to create repositories "
 
"everywhere. That might change in future versions."
 
msgstr ""
 
"Hinweis: dadurch erhalten auch alle Benutzer API-Zugriff, um überall "
 
"Repositories zu erstellen. Das kann sich in zukünftigen Versionen ändern."
 

	
 
msgid "Repository creation with group write access"
 
msgstr "Repository-Erstellung mit Gruppen-Schreibzugriff"
 

	
 
msgid ""
 
"With this, write permission to a repository group allows creating "
 
"repositories inside that group. Without this, group write permissions "
 
"mean nothing."
 
msgstr ""
 
"Falls aktiv, gewährt dies das Recht zum Erzeugen von Repositories in "
 
"einer Repository-Gruppe. Falls inaktiv, sind Gruppen-"
 
"Schreibberechtigungen wirkungslos."
 

	
 
msgid "User group creation"
 
msgstr "Benutzergruppen Erstellung"
 

	
 
msgid "Enable this to allow non-admins to create user groups."
 
msgstr ""
 
"Aktivieren Sie dies, damit Nicht-Administratoren Benutzergruppen "
 
"erstellen können."
 

	
 
msgid "Repository forking"
 
msgstr "Repository-forking"
 

	
 
msgid "Enable this to allow non-admins to fork repositories."
 
msgstr ""
 
"Aktivieren Sie dies, um Nichtadministratoren zu erlauben, Repositories zu "
 
"forken."
 

	
 
msgid "Registration"
 
msgstr "Registrierung"
 

	
 
msgid "All IP addresses are allowed."
 
msgstr "Alle IP-Adressen sind zulässig."
 

	
 
msgid "New IP address"
 
msgstr "Neue IP-Adresse"
 

	
 
msgid "Repository Groups"
 
msgstr "Repositorygruppen"
 

	
 
msgid "Group name"
 
msgstr "Gruppen name"
 

	
 
msgid "Group parent"
 
msgstr "Übergeordnete Gruppe"
 

	
 
msgid "Copy parent group permissions"
 
msgstr "Rechte der übergeordneten Gruppe kopieren"
 

	
 
msgid "Copy permission set from parent repository group."
 
msgstr "Rechte der übergeordneten Repositorygruppe kopieren."
 

	
 
msgid "%s Repository Group Settings"
 
msgstr "%s Einstellungen für Repositorygruppen"
 

	
 
msgid "Add Child Group"
 
msgstr "Untergruppe hinzufügen"
 

	
 
msgid "Settings"
 
msgstr "Einstellungen"
 

	
 
msgid "Advanced"
 
msgstr "Erweitert"
 

	
 
msgid "Permissions"
 
msgstr "Rechte"
 

	
 
msgid "Repository Group: %s"
 
msgstr "Repositorygruppe: %s"
 

	
 
msgid "Top level repositories"
 
msgstr "Repositories oberster Ebene"
 

	
 
msgid "Total repositories"
 
msgstr "Alle Repositories"
 

	
 
msgid "Children groups"
 
msgstr "Untergruppen"
 

	
 
msgid "Created on"
 
msgstr "Erstellt am"
 

	
 
msgid "Confirm to delete this group: %s with %s repository"
 
msgid_plural "Confirm to delete this group: %s with %s repositories"
 
msgstr[0] "Löschen der Gruppe bestätigen: %s mit %s Repository"
 
msgstr[1] "Löschen der Gruppe bestätigen: %s mit %s Repositories"
 

	
 
msgid "Delete this repository group"
 
msgstr "Diese Repositorygruppe löschen"
 

	
 
msgid "Not visible"
 
msgstr "Nicht sichtbar"
 

	
 
msgid "Visible"
 
msgstr "Sichtbar"
 

	
 
msgid "Add/Edit groups"
 
msgstr "Benutzergruppen hinzufügen oder ändern"
 

	
 
msgid "Default"
 
msgstr "Vorgabe"
 

	
 
msgid "Revoke"
 
msgstr "Zurückziehen"
 

	
 
msgid "Add new"
 
msgstr "Neues hinzufügen"
 

	
 
msgid "Apply to children"
 
msgstr "Auf untergeordnete Elemente anwenden"
 

	
 
msgid "Both"
 
msgstr "Beide"
 

	
 
msgid ""
 
"Set or revoke permission to all children of that group, including non-"
 
"private repositories and other groups if selected."
 
msgstr ""
 
"Setzen oder zurückziehen von Berechtigungen bezüglich aller "
 
"untergeordneten Elemente, einschließlich nicht-privater Repositories und "
 
"anderer Gruppen, falls ausgewählt."
 

	
 
msgid "Remove this group"
 
msgstr "Diese Gruppe löschen"
 

	
 
msgid "Confirm to delete this group"
 
msgstr "Löschen der Gruppe bestätigen"
 

	
 
msgid "Repository group %s"
 
msgstr "Repository-Gruppe %s"
 

	
 
msgid "Repository Groups Administration"
 
msgstr "Repositorygruppenverwaltung"
 

	
 
msgid "Number of Top-level Repositories"
 
msgstr "Anzahl der Repositories oberster Ebene"
 

	
 
msgid "Clone remote repository"
 
msgstr "Entferntes Repository clonen"
 

	
 
msgid ""
 
"Optional: URL of a remote repository. If set, the repository will be "
 
"created as a clone from this URL."
 
msgstr ""
 
"Optional: URL eines entfernten Repositories. Falls gesetzt, dann wird das "
 
"Repository als Clon von dieser URL erstellt."
 

	
 
msgid ""
 
"Keep it short and to the point. Use a README file for longer descriptions."
 
msgstr ""
 
"Halten Sie es kurz und prägnant. Benutzen Sie eine README-Datei für "
 
"längere Beschreibungen."
 

	
 
msgid "Optionally select a group to put this repository into."
 
msgstr ""
 
"Wähle bei Bedarf eine Gruppe, der dieses Repository zugeordnet werden "
 
"soll."
 

	
 
msgid "Type of repository to create."
 
msgstr "Repository Typ der erstellt werden soll."
 

	
 
msgid "Landing revision"
 
msgstr "Start Revision"
 

	
 
msgid ""
 
"Default revision for files page, downloads, full text search index and "
 
"readme generation"
 
msgstr ""
 
"Vorgabe-Revision für Datei-Seiten, Downloads, Volltext-Indizierung und "
 
"Doku-Erzeugung"
 

	
 
msgid "%s Creating Repository"
 
msgstr "%s Erstelle Repository"
 

	
 
msgid "Creating repository"
 
msgstr "Repository erzeugen"
 

	
 
msgid ""
 
"Repository \"%(repo_name)s\" is being created, you will be redirected "
 
"when this process is finished.repo_name"
 
msgstr ""
 
"Repository \"%(repo_name)s\" wird erzeugt. Sie werden dorthin umgeleitet, "
 
"sobald der Prozess abgeschlossen ist."
 

	
 
msgid ""
 
"We're sorry but error occurred during this operation. Please check your "
 
"Kallithea server logs, or contact administrator."
 
msgstr ""
 
"Bedauerlicherweise ist bei dieser Operation ein Fehler aufgetreten. Bitte "
 
"prüfen Sie die Kallithea-Server-Logs or kontaktieren Sie die "
 
"Administrierenden."
 

	
 
msgid "%s Repository Settings"
 
msgstr "%s Repositoryeinstellungen"
 

	
 
msgid "Extra Fields"
 
msgstr "Extra-Feld"
 

	
 
msgid "Remote"
 
msgstr "Entfernt"
 

	
 
msgid "Statistics"
 
msgstr "Statistiken"
 

	
 
msgid "Parent"
 
msgstr "Übergeordnet"
 

	
 
msgid "Set"
 
msgstr "Setzen"
 

	
 
msgid "Manually set this repository as a fork of another from the list."
 
msgstr ""
 
"Manuell dieses Repository als Fork einem anderen aus der List zuordnen."
 

	
 
msgid "Public Journal Visibility"
 
msgstr "Sichtbarkeit des öffentlichen Logbuches"
 

	
 
msgid "Remove from public journal"
 
msgstr "Entferne aus dem Öffentlichen Logbuch"
 

	
 
msgid "Add to Public Journal"
 
msgstr "Zum öffentlichen Logbuch hinzufügen"
 

	
 
msgid ""
 
"All actions done in this repository will be visible to everyone in the "
 
"public journal."
 
msgstr ""
 
"Alle Aktionen, die in diesem Repository ausgeführt wurden, sind im "
 
"öffentlichen Logbuch für jeden einsehbar."
 

	
 
msgid "Confirm to delete this repository: %s"
 
msgstr "Löschen des Repositorys bestätigen: %s"
 

	
 
msgid "Delete this Repository"
 
msgstr "Dieses Repository löschen"
 

	
 
msgid "This repository has %s fork"
 
msgid_plural "This repository has %s forks"
 
msgstr[0] "Dieses Repository hat %s Fork"
 
msgstr[1] "Dieses Repository hat %s Forks"
 

	
 
msgid "Detach forks"
 
msgstr "Fork abtrennen"
 

	
 
msgid "Delete forks"
 
msgstr "Forks löschen"
 

	
 
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 ""
 
"Das gelöschte Repository wird beiseitegelegt und versteckt, bis ein "
 
"Administrierender es verfallen lässt. Der Administrierende kann es sowohl "
 
"permanent löschen oder wiederherstellen."
 

	
 
msgid "Label"
 
msgstr "Bezeichnung"
 

	
 
msgid "Key"
 
msgstr "Schlüssel"
 

	
 
msgid "Confirm to delete this field: %s"
 
msgstr "Löschen des Felds bestätigen: %s"
 

	
 
msgid "New field key"
 
msgstr "Eindeutiges Kennzeichen des neuen Felds"
 

	
 
msgid "New field label"
 
msgstr "Neue Bezeichnung des Felds"
 

	
 
msgid "Enter short label"
 
msgstr "Eingabe einer kurzen Bezeichnung"
 

	
 
msgid "New field description"
 
msgstr "Beschreibung des neuen Felds"
 

	
 
msgid "Enter description of a field"
 
msgstr "Beschreibung eines Felds eingeben"
 

	
 
msgid "Extra fields are disabled."
 
msgstr "Zusatzfelder sind deaktiviert."
 

	
 
msgid "Private Repository"
 
msgstr "Privates Repository"
 

	
 
msgid "Fork of repository"
 
msgstr "Fork des Repository"
 

	
 
msgid "Remote repository URL"
 
msgstr "URL des entfernten Repository"
 

	
 
msgid "Pull Changes from Remote Repository"
 
msgstr "Hole Änderungen vom entfernten Repository"
 

	
 
msgid "Confirm to pull changes from remote repository."
 
msgstr "Bestätige die Abholung von Änderungen vom entfernten Repository."
 

	
 
msgid "This repository does not have a remote repository URL."
 
msgstr "Für dieses Repository ist keine nicht-lokale URL angegeben."
 

	
 
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 ""
 
"Falls dieses Repository umbenannt oder in eine andere Gruppe verschoben "
 
"wird, ändert sich seine URL.\n"
 
"Die Verwendung der permanenten URL garantiert, dass dieses Repository "
 
"immer über diese URL erreichbar sein wird.\n"
 
"Dies ist insbesondere für CI-Systeme oder in Fällen nützlich, in denen "
 
"die URL des Repositories bei Dritten dauerhaft eingetragen wird."
 

	
 
msgid "Remote repository"
 
msgstr "Entferntes Repository"
 

	
 
msgid "Repository URL"
 
msgstr "Repository URL"
 

	
 
msgid ""
 
"Optional: URL of a remote repository. If set, the repository can be "
 
"pulled from this URL."
 
msgstr ""
 
"Optional: URL eines entfernten Repositories. Falls gesetzt, dann kann das "
 
"Repository von dieser URL bezogen werden."
 

	
 
msgid "Default revision for files page, downloads, whoosh and readme"
 
msgstr "Standardrevision für Dateiseite, Downloads, Whoosh und Readme"
 

	
 
msgid "Type name of user"
 
msgstr "Typname des Benutzers"
 

	
 
msgid "Change owner of this repository."
 
msgstr "Besitzer des Repositorys ändern."
 

	
 
msgid "Processed commits"
 
msgstr "Verarbeitete Commits"
 

	
 
msgid "Processed progress"
 
msgstr "Verarbeiteter Fortschritt"
 

	
 
msgid "Reset Statistics"
 
msgstr "Statistiken zurücksetzen"
 

	
 
msgid "Confirm to remove current statistics."
 
msgstr "Bestätigen Sie, um die aktuellen Statistiken zu entfernen."
 

	
 
msgid "Repositories Administration"
 
msgstr "Repositoryverwaltung"
 

	
 
msgid "State"
 
msgstr "Zustand"
 

	
 
msgid "Settings Administration"
 
msgstr "Einstellungsverwaltung"
 

	
 
msgid "VCS"
 
msgstr "VCS"
 

	
 
msgid "Remap and Rescan"
 
msgstr "Neu zuordnen und neu scannen"
 

	
 
msgid "Visual"
 
msgstr "Visuell"
 

	
 
msgid "Hooks"
 
msgstr "Hooks"
 

	
 
msgid "Full Text Search"
 
msgstr "Volltextsuche"
 

	
 
msgid "System Info"
 
msgstr "Systeminfo"
 

	
 
msgid "Send test email to"
 
msgstr "Test-E-Mail senden an"
 

	
 
msgid "Send"
 
msgstr "Senden"
 

	
 
msgid "Site branding"
 
msgstr "Website-Branding"
 

	
 
msgid "Set a custom title for your Kallithea Service."
 
msgstr ""
 
"Legen Sie einen benutzerdefinierten Titel für Ihren Kallithea-Dienst fest."
 

	
 
msgid "HTTP authentication realm"
 
msgstr "HTTP-Authentifizierungsrealm"
 

	
 
msgid "HTML/JavaScript/CSS customization block"
 
msgstr "HTML/JavaScript/CSS Anpassungsblock"
 

	
 
msgid "ReCaptcha public key"
 
msgstr "ReCaptcha öffentlicher Schlüssel"
 

	
 
msgid "Public key for reCaptcha system."
 
msgstr "Öffentlicher Schlüssel für das reCaptcha-System."
 

	
 
msgid "ReCaptcha private key"
 
msgstr "ReCaptcha privater Schlüssel"
 

	
 
msgid ""
 
"Private key for reCaptcha system. Setting this value will enable captcha "
 
"on registration."
 
msgstr ""
 
"Privater Schlüssel für das reCaptcha-System. Wenn Sie diesen Wert "
 
"einstellen, wird das Captcha bei der Registrierung aktiviert."
 

	
 
msgid "Save Settings"
 
msgstr "Einstellungen speichern"
 

	
 
msgid "Built-in Mercurial Hooks (Read-Only)"
 
msgstr "Eingebaute Mercurial Hooks (Read -Only)"
 

	
 
msgid "Custom Hooks"
 
msgstr "Benutzerdefinierte Hooks"
 

	
 
msgid ""
 
"Hooks can be used to trigger actions on certain events such as push / "
 
"pull. They can trigger Python functions or external applications."
 
msgstr ""
 
"Mit Hilfe von Hooks können bei bestimmten Ereignissen, wie z.B. Push / "
 
"Pull, Aktionen ausgelöst werden. Sie können Python-Funktionen oder "
 
"externe Anwendungen auslösen."
 

	
 
msgid "Failed to remove hook"
 
msgstr "Hook konnte nicht entfernt werden"
 

	
 
msgid "Delete records of missing repositories"
 
msgstr "Datensätze fehlender Repositories löschen"
 

	
 
msgid ""
 
"Check this option to remove all comments, pull requests and other records "
 
"related to repositories that no longer exist in the filesystem."
 
msgstr ""
 
"Aktivieren Sie diese Option, um alle Kommentare, Pull-Requests und andere "
 
"Datensätze zu entfernen, die sich auf Repositories beziehen, die nicht "
 
"mehr im Dateisystem vorhanden sind."
 

	
 
msgid "Invalidate cache for all repositories"
 
msgstr "Cache für alle Repositories entwerten"
 

	
 
msgid "Check this to reload data and clear cache keys for all repositories."
 
msgstr ""
 
"Aktivieren Sie dies, um Daten neu zu laden und Cache-Schlüssel für alle "
 
"Repositories zu löschen."
 

	
 
msgid "Install Git hooks"
 
msgstr "Git-Hooks installieren"
 

	
 
msgid ""
 
"Verify if Kallithea's Git hooks are installed for each repository. "
 
"Current hooks will be updated to the latest version."
 
msgstr ""
 
"Überprüfen Sie, ob die Git-Hooks von Kallithea für jedes Repository "
 
"installiert sind. Aktuelle Hooks werden auf die neueste Version "
 
"aktualisiert."
 

	
 
msgid "Overwrite existing Git hooks"
 
msgstr "Bestehende Git-Hooks überschreiben"
 

	
 
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 ""
 
"Wenn Sie Git-Hooks installieren, überschreiben Sie alle vorhandenen "
 
"Hooks, auch wenn sie nicht von Kallithea zu kommen scheinen. WARNUNG: "
 
"Diese Operation zerstört alle benutzerdefinierten Git-Hooks, die Sie "
 
"möglicherweise von Hand bereitgestellt haben!"
 

	
 
msgid "Rescan Repositories"
 
msgstr "Repositories erneut scannen"
 

	
 
msgid "Index build option"
 
msgstr "Option zum Aufbau eines Index"
 

	
 
msgid "Build from scratch"
 
msgstr "Von Grund auf neu bauen"
 

	
 
msgid ""
 
"This option completely reindexeses all of the repositories for proper "
 
"This option completely reindexes all of the repositories for proper "
 
"fulltext search capabilities."
 
msgstr ""
 
"Diese Option führt zu einer vollständigen Neuindizierung aller "
 
"Repositories für eine korrekte Volltextsuche."
 

	
 
msgid "Reindex"
 
msgstr "Erneut Indizieren"
 

	
 
msgid "Checking for updates..."
 
msgstr "Prüfe auf Updates..."
 

	
 
msgid "Kallithea version"
 
msgstr "Kallithea-Version"
 

	
 
msgid "Kallithea configuration file"
 
msgstr "Kallithea Konfigurationsdatei"
 

	
 
msgid "Python version"
 
msgstr "Python-Version"
 

	
 
msgid "Platform"
 
msgstr "Plattform"
 

	
 
msgid "Git version"
 
msgstr "Git-Version"
 

	
 
msgid "Git path"
 
msgstr "Git-Pfad"
 

	
 
msgid "Python Packages"
 
msgstr "Python-Pakete"
 

	
 
msgid "Show repository size after push"
 
msgstr "Zeigt die Größe des Repositories nach dem Push an"
 

	
 
msgid "Update repository after push (hg update)"
 
msgstr "Repository nach dem Push aktualisieren (hg update)"
 

	
 
msgid "Mercurial extensions"
 
msgstr "Mercurial-Erweiterungen"
 

	
 
msgid "Enable largefiles extension"
 
msgstr "Erweiterung largefiles aktivieren"
 

	
 
msgid "Location of repositories"
 
msgstr "Ort der Repositories"
 

	
 
msgid ""
 
"Click to unlock. You must restart Kallithea in order to make this setting "
 
"take effect."
 
msgstr ""
 
"Zum Entsperren klicken. Sie müssen Kallithea neu starten, damit diese "
 
"Einstellung wirksam wird."
 

	
 
msgid ""
 
"Filesystem location where repositories are stored. After changing this "
 
"value, a restart and rescan of the repository folder are both required."
 
msgstr ""
 
"Dateisystem-Speicherort, an dem die Repositories gespeichert sind. Nach "
 
"dem Ändern dieses Wertes sind sowohl ein Neustart als auch ein erneuter "
 
"Scan des Repository-Ordners erforderlich."
 

	
 
msgid "General"
 
msgstr "Allgemein"
 

	
 
msgid "Use repository extra fields"
 
msgstr "Zusätzliche Repository-Felder verwenden"
 

	
 
msgid "Allows storing additional customized fields per repository."
 
msgstr ""
 
"Ermöglicht die Speicherung zusätzlicher benutzerdefinierter Felder pro "
 
"Repository."
 

	
 
msgid "Show Kallithea version"
 
msgstr "Zeige Kallithea-Version"
 

	
 
msgid ""
 
"Shows or hides a version number of Kallithea displayed in the footer."
 
msgstr ""
 
"Zeigt oder verbirgt eine Versionsnummer von Kallithea, die in der "
 
"Fußzeile angezeigt wird."
 

	
 
msgid "Show user Gravatars"
 
msgstr "Benutzer Gravatare anzeigen"
 

	
 
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 ""
 
"Gravatar URL ermöglicht es Ihnen, eine andere Avatar-Serveranwendung zu "
 
"verwenden.\n"
 
"                                                        Die folgenden "
 
"Variablen der URL werden entsprechend ersetzt.\n"
 
"                                                        {scheme}    "
 
"'http' oder'https', die vom laufenden Kallithea-Server gesendet werden,\n"
 
"                                                        {email}    "
 
"Benutzer-E-Mail,\n"
 
"                                                        {md5email}  md5 "
 
"Hash der Benutzer-E-Mail (wie bei gravatar.com),\n"
 
"                                                        {size}       "
 
"Größe des Bildes, das von der Serveranwendung erwartet wird,\n"
 
"                                                        {netloc}    "
 
"Netzwerkstandort/Server-Host des laufenden Kallithea-Servers"
 

	
 
msgid ""
 
"Number of items displayed in the repository pages before pagination is "
 
"shown."
 
msgstr ""
 
"Anzahl der Elemente, die auf den Repository-Seiten angezeigt werden, "
 
"bevor der Seitenumbruch angezeigt wird."
 

	
 
msgid "Admin page size"
 
msgstr "Größe der Admin-Seite"
 

	
 
msgid ""
 
"Number of items displayed in the admin pages grids before pagination is "
 
"shown."
 
msgstr ""
 
"Anzahl der Elemente, die in den Gittern der Admin-Seiten angezeigt "
 
"werden, bevor der Seitenumbruch angezeigt wird."
 

	
 
msgid "Icons"
 
msgstr "Icons"
 

	
 
msgid "Show public repository icon on repositories"
 
msgstr "Öffentliches Repository-Symbol in Repositories anzeigen"
 

	
 
msgid "Show private repository icon on repositories"
 
msgstr "Privates Repository-Symbol in Repositories anzeigen"
 

	
 
msgid "Show public/private icons next to repository names."
 
msgstr ""
 
"Zeigt öffentliche/private Symbole neben den Namen der Repositories an."
 

	
 
msgid ""
 
"Parses meta tags from the repository description field and turns them "
 
"into colored tags."
 
msgstr ""
 
"Analysiert Meta-Tags aus dem Beschreibungsfeld des Repositorys und "
 
"verwandelt sie in farbige Tags."
 

	
 
msgid "Stylify recognised meta tags:"
 
msgstr "Erkannte Meta-Tags stilisieren:"
 

	
 
msgid "Add user group"
 
msgstr "Benutzergruppe hinzufügen"
 

	
 
msgid "User Groups"
 
msgstr "Benutzergruppen"
 

	
 
msgid "Add User Group"
 
msgstr "Benutzergruppe hinzufügen"
 

	
 
msgid "Short, optional description for this user group."
 
msgstr "Kurze, optionale Beschreibung für diese Benutzergruppe."
 

	
 
msgid "Active"
 
msgstr "Aktiv"
 

	
 
msgid "User Group: %s"
 
msgstr "Benutzergruppe: %s"
 

	
 
msgid "Members"
 
msgstr "Mitglieder"
 

	
 
msgid "Confirm to delete this user group: %s"
 
msgstr "Bestätigen, um diese Benutzergruppe zu löschen: %s"
 

	
 
msgid "Delete this user group"
 
msgstr "Diese Benutzergruppe löschen"
 

	
 
msgid "No members yet"
 
msgstr "Noch keine Mitglieder"
 

	
 
msgid "Chosen group members"
 
msgstr "Ausgewählte Grppenmitglieder"
 

	
 
msgid "Available members"
 
msgstr "Verfügbare Mitglieder"
 

	
 
msgid "User Groups Administration"
 
msgstr "Benutzergruppenverwaltung"
 

	
 
msgid "Add user"
 
msgstr "Benutzer hinzufügen"
 

	
 
msgid "Users"
 
msgstr "Benutzer"
 

	
 
msgid "Add User"
 
msgstr "Benutzer hinzufügen"
 

	
 
msgid "Password confirmation"
 
msgstr "Passwortbestätigung"
 

	
 
msgid "Emails"
 
msgstr "E-Mails"
 

	
 
msgid "User: %s"
 
msgstr "Benutzer: %s"
 

	
 
msgid "Last Login"
 
msgstr "Letzter Login"
 

	
 
msgid "Member of User Groups"
 
msgstr "Mitglieder der Benutzergruppe"
 

	
 
msgid "Delete this user"
 
msgstr "Diesen Benutzer löschen"
 

	
 
msgid "Users Administration"
 
msgstr "Benutzerverwaltung"
 

	
 
msgid "Auth Type"
 
msgstr "Authentifizierungsart"
 

	
 
msgid "Support"
 
msgstr "Support"
 

	
 
msgid "Mercurial repository"
 
msgstr "Mercurial Repository"
 

	
 
msgid "Git repository"
 
msgstr "Git Repository"
 

	
 
msgid "Create Fork"
 
msgstr "Fork erstellen"
 

	
 
msgid "Summary"
 
msgstr "Zusammenfassung"
 

	
 
msgid "Files"
 
msgstr "Dateien"
 

	
 
msgid "Pull Requests"
 
msgstr "Pull Requests"
 

	
 
msgid "Options"
 
msgstr "Optionen"
 

	
 
msgid "Compare Fork"
 
msgstr "Fork vergleichen"
 

	
 
msgid "No matches found"
 
msgstr "Keine Übereinstimmungen gefunden"
 

	
 
msgid "Public journal"
 
msgstr "Öffentliches Logbuch"
 

	
 
msgid "My Pull Requests"
 
msgstr "Meine Pull Requests"
 

	
 
msgid "Not Logged In"
 
msgstr "Nicht eingeloggt"
 

	
 
msgid "Permission"
 
msgstr "Rechte"
 

	
 
msgid "Edit Permission"
 
msgstr "Berechtigungen editieren"
 

	
 
msgid "Add Another Comment"
 
msgstr "Einen weiteren Kommentar hinzufügen"
 

	
 
msgid "Group"
 
msgstr "Gruppe"
 

	
 
msgid "Confirm to revoke permission for {0}: {1} ?"
 
msgstr "Widerruf der Rechte für {0}: {1} bestätigen?"
 

	
 
msgid "Select changeset"
 
msgstr "Änderungssätze auswählen"
 

	
 
msgid "Specify changeset"
 
msgstr "Changeset angeben"
 

	
 
msgid "Click to sort ascending"
 
msgstr "Klicken um Aufsteigend zu Sortieren"
 

	
 
msgid "Click to sort descending"
 
msgstr "Klicken um Absteigend zu Sortieren"
 

	
 
msgid "No records found."
 
msgstr "Keine Datensätze gefunden."
 

	
 
msgid "Data error."
 
msgstr "Datenfehler."
 

	
 
msgid "Loading..."
 
msgstr "Lade..."
 

	
 
msgid "Go to tip of repository"
 
msgstr "Gehe zum Tip des Repositorys"
 

	
 
msgid "There are no changes yet"
 
msgstr "Bisher gibt es keine Änderungen"
 

	
 
msgid "Branch %s"
 
msgstr "Branch %s"
 

	
 
msgid "No title"
 
msgstr "Kein Titel"
 

	
 
msgid "Delete comment?"
 
msgstr "Kommentar löschen?"
 

	
 
msgid "Set changeset status"
 
msgstr "Setze Changesetstatus"
 

	
 
msgid "No change"
 
msgstr "Keine Änderungen"
 

	
 
msgid "Close"
 
msgstr "Schließen"
 

	
 
msgid "Comment"
 
msgstr "Kommentar"
 

	
 
msgid "%d comment"
 
msgid_plural "%d comments"
 
msgstr[0] "%d Kommentar"
 
msgstr[1] "%d Kommentare"
 

	
 
msgid "%d inline"
 
msgid_plural "%d inline"
 
msgstr[0] "%d inline"
 
msgstr[1] "%d inline"
 

	
 
msgid "%d general"
 
msgid_plural "%d general"
 
msgstr[0] "%d generell"
 
msgstr[1] "%d generell"
 

	
 
msgid "Deleted"
 
msgstr "Gelöscht"
 

	
 
msgid "Renamed"
 
msgstr "Umbenannt"
 

	
 
msgid "%s changesets"
 
msgstr "%s Changesets"
 

	
 
msgid "behind"
 
msgstr "zurück"
 

	
 
msgid "Public repository"
 
msgstr "Öffenentliches Repository"
 

	
 
msgid "Subscribe to %s rss feed"
 
msgstr "Abonniere den %s RSS Feed"
 

	
 
msgid "Subscribe to %s atom feed"
 
msgstr "Abonniere den %s ATOM Feed"
 

	
 
msgid "Hello %s"
 
msgstr "Hallo %s"
 

	
 
msgid "or"
 
msgstr "oder"
 

	
 
msgid "Upload File"
 
msgstr "Datei hochladen"
 

	
 
msgid "Commit Changes"
 
msgstr "Änderungen einchecken"
 

	
 
msgid "Size"
 
msgstr "Größe"
 

	
 
msgid "Last Modified"
 
msgstr "Zuletzt geändert"
 

	
 
msgid "Delete file"
 
msgstr "Datei löschen"
 

	
 
msgid "%s author"
 
msgid_plural "%s authors"
 
msgstr[0] "%s Autor"
 
msgstr[1] "%s Autoren"
 

	
 
msgid "Go Back"
 
msgstr "Zurück"
 

	
 
msgid "Private"
 
msgstr "Privat"
 

	
 
msgid "Copy permissions"
 
msgstr "Berechtigungen kopieren"
 

	
 
msgid "ATOM journal feed"
 
msgstr "ATOM Logbuch Feed"
 

	
 
msgid "RSS journal feed"
 
msgstr "RSS Logbuch Feed"
 

	
 
msgid "My Repositories"
 
msgstr "Meine Repositories"
 

	
 
msgid "ATOM public journal feed"
 
msgstr "ATOM Feed für das Öffentliche Logbuch"
 

	
 
msgid "RSS public journal feed"
 
msgstr "RSS Feed für das Öffentliche Logbuch"
 

	
 
msgid "New Pull Request"
 
msgstr "Neuer Pull Request"
 

	
 
msgid "Title"
 
msgstr "Titel"
 

	
 
msgid "Revision"
 
msgstr "Revision"
 

	
 
msgid "Age"
 
msgstr "Alter"
 

	
 
msgid "Delete Pull Request"
 
msgstr "Pull Request löschen"
 

	
 
msgid "Summarize the changes"
 
msgstr "Zusammenfassung der Änderungen"
 

	
 
msgid "on"
 
msgstr "in"
 

	
 
msgid "Cancel Changes"
 
msgstr "Änderungen verwerfen"
 

	
 
msgid "Remove reviewer"
 
msgstr "Reviewer entfernen"
 

	
 
msgid "Potential Reviewers"
 
msgstr "Potentielle Reviewer"
 

	
 
msgid "Pull Request Content"
 
msgstr "Inhalt des Pull Requests"
 

	
 
msgid "Pull Requests to '%s'"
 
msgstr "Pull Requests für '%s'"
 

	
 
msgid "Open New Pull Request"
 
msgstr "Einen neuen Pull Request eröffnen"
 

	
 
msgid "Show Pull Requests to %s"
 
msgstr "Zeige Pull Requests für '%s'"
 

	
 
msgid "Show Pull Requests from '%s'"
 
msgstr "Zeige Pull Requests von '%s'"
 

	
 
msgid "Pull Requests Created by Me"
 
msgstr "Von mir erstellte Pull Requests"
 

	
 
msgid "Search in All Repositories"
 
msgstr "Suche in allen Repositories"
 

	
 
msgid "Search term"
 
msgstr "Suchbegriff"
 

	
 
msgid "Search in"
 
msgstr "Suchen in"
 

	
 
msgid "File contents"
 
msgstr "Dateiinhalt"
 

	
 
msgid "Commit messages"
 
msgstr "Commit Nachrichten"
 

	
 
msgid "File names"
 
msgstr "Dateinamen"
 

	
 
msgid "Permission denied"
 
msgstr "Zugriff verweigert"
 

	
 
msgid "Enable"
 
msgstr "Aktiviere"
 

	
 
msgid "files"
 
msgstr "Dateien"
 

	
 
msgid "Show more"
 
msgstr "Mehr anzeigen"
 

	
 
msgid "commits"
 
msgstr "Commits"
 

	
 
msgid "files added"
 
msgstr "Dateien hinzugefügt"
 

	
 
msgid "files changed"
 
msgstr "Dateien geändert"
 

	
 
msgid "files removed"
 
msgstr "Dateien entfernt"
 

	
 
msgid "commit"
 
msgstr "Commit"
 

	
 
msgid "file added"
 
msgstr "Datei hinzugefügt"
 

	
 
msgid "file changed"
 
msgstr "Datei geändert"
 

	
 
msgid "file removed"
 
msgstr "Datei entfernt"
 

	
 
msgid "Clone from"
 
msgstr "Clone von"
 

	
 
msgid "Clone URL"
 
msgstr "Clone-URL"
 

	
 
msgid "Download as zip"
 
msgstr "Herunterladen als zip"
 

	
 
msgid "Feed"
 
msgstr "Feed"
 

	
 
msgid "Latest Changes"
 
msgstr "Letzte Änderungen"
 

	
 
msgid "Quick Start"
 
msgstr "Schnelleinstieg"
 

	
 
msgid "Add or upload files directly via Kallithea"
 
msgstr "Dateien direkt über Kallithea hinzufügen oder hochladen"
 

	
 
msgid "Readme file from revision %s:%s"
 
msgstr "Liesmich-Datei von Revision %s:%s"
 

	
 
msgid "Download %s as %s"
 
msgstr "%s als %s herunterladen"

Changeset was too big and was cut off... Show full diff anyway

0 comments (0 inline, 0 general)