Changeset - 802c94bdfc85
[Not reviewed]
beta
3 11 0
Marcin Kuzminski - 13 years ago 2013-03-28 02:57:05
marcin@python-works.com
#749 and #516 Removed dupliciting of repo settings for rhodecode admins and repo admins
- repo admin now is allowed the same set of operations as the rhodecode admin
- single logic for forms/validations/permissions
- fixes #805 update external repo via webinterface
-
14 files changed with 134 insertions and 531 deletions:
0 comments (0 inline, 0 general)
rhodecode/config/routing.py
Show inline comments
 
@@ -106,6 +106,9 @@ def make_map(config):
 
            conditions=dict(method=["GET"]))
 
        m.connect("new_repo", "/repos/new",
 
             action="new", conditions=dict(method=["GET"]))
 
        #TODO: refactor the name
 
        m.connect("admin_settings_create_repository", "/create_repository",
 
                  action="create_repository", conditions=dict(method=["GET"]))
 
        m.connect("formatted_new_repo", "/repos/new.{format}",
 
             action="new", conditions=dict(method=["GET"]))
 
        m.connect("/repos/{repo_name:.*?}",
 
@@ -114,10 +117,6 @@ def make_map(config):
 
        m.connect("/repos/{repo_name:.*?}",
 
             action="delete", conditions=dict(method=["DELETE"],
 
                                              function=check_repo))
 
        # no longer used:
 
        m.connect("edit_repo_admin", "/repos/{repo_name:.*?}/edit",
 
             action="edit", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        m.connect("formatted_edit_repo", "/repos/{repo_name:.*?}.{format}/edit",
 
             action="edit", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
@@ -162,6 +161,10 @@ def make_map(config):
 
        m.connect('repo_locking', "/repo_locking/{repo_name:.*?}",
 
                  action="repo_locking", conditions=dict(method=["PUT"],
 
                                                      function=check_repo))
 
        m.connect('toggle_locking', "/locking_toggle/{repo_name:.*?}",
 
                  action="toggle_locking", conditions=dict(method=["GET"],
 
                                                      function=check_repo))
 

	
 
        #repo fields
 
        m.connect('create_repo_fields', "/repo_fields/{repo_name:.*?}/new",
 
                  action="create_repo_field", conditions=dict(method=["PUT"],
 
@@ -334,8 +337,6 @@ def make_map(config):
 
                  action="my_account", conditions=dict(method=["GET"]))
 
        m.connect("admin_settings_my_account_update", "/my_account_update",
 
                  action="my_account_update", conditions=dict(method=["PUT"]))
 
        m.connect("admin_settings_create_repository", "/create_repository",
 
                  action="create_repository", conditions=dict(method=["GET"]))
 
        m.connect("admin_settings_my_repos", "/my_account/repos",
 
                  action="my_account_my_repos", conditions=dict(method=["GET"]))
 
        m.connect("admin_settings_my_pullrequests", "/my_account/pull_requests",
 
@@ -466,7 +467,13 @@ def make_map(config):
 
                controller='changeset', revision='tip',
 
                conditions=dict(function=check_repo))
 

	
 
    rmap.connect("edit_repo", "/{repo_name:.*?}/edit",
 
    # no longer user, but kept for routes to work
 
    rmap.connect("_edit_repo", "/{repo_name:.*?}/edit",
 
                 controller='admin/repos', action="edit",
 
                 conditions=dict(method=["GET"], function=check_repo)
 
                 )
 

	
 
    rmap.connect("edit_repo", "/{repo_name:.*?}/settings",
 
                 controller='admin/repos', action="edit",
 
                 conditions=dict(method=["GET"], function=check_repo)
 
                 )
 
@@ -635,22 +642,6 @@ def make_map(config):
 
                controller='files', action='nodelist',
 
                conditions=dict(function=check_repo))
 

	
 
    rmap.connect('repo_settings_delete', '/{repo_name:.*?}/settings',
 
                controller='settings', action="delete",
 
                conditions=dict(method=["DELETE"], function=check_repo))
 

	
 
    rmap.connect('repo_settings_update', '/{repo_name:.*?}/settings',
 
                controller='settings', action="update",
 
                conditions=dict(method=["PUT"], function=check_repo))
 

	
 
    rmap.connect('repo_settings_home', '/{repo_name:.*?}/settings',
 
                controller='settings', action='index',
 
                conditions=dict(function=check_repo))
 

	
 
    rmap.connect('toggle_locking', "/{repo_name:.*?}/locking_toggle",
 
                 controller='settings', action="toggle_locking",
 
                 conditions=dict(method=["GET"], function=check_repo))
 

	
 
    rmap.connect('repo_fork_create_home', '/{repo_name:.*?}/fork',
 
                controller='forks', action='fork_create',
 
                conditions=dict(function=check_repo, method=["POST"]))
rhodecode/controllers/admin/repos.py
Show inline comments
 
@@ -38,7 +38,7 @@ import rhodecode
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
 
    HasPermissionAnyDecorator, HasRepoPermissionAllDecorator, NotAnonymous,\
 
    HasPermissionAny, HasReposGroupPermissionAny
 
    HasPermissionAny, HasReposGroupPermissionAny, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
 
from rhodecode.lib.helpers import get_token
 
@@ -202,16 +202,27 @@ class ReposController(BaseRepoController
 
        #redirect to our new repo !
 
        return redirect(url('summary_home', repo_name=new_repo.repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def new(self, format='html'):
 
        """
 
        WARNING: this function is depracated see settings.create_repo !!
 
    @NotAnonymous()
 
    def create_repository(self):
 
        """GET /_admin/create_repository: Form to create a new item"""
 
        new_repo = request.GET.get('repo', '')
 
        parent_group = request.GET.get('parent_group')
 
        if not HasPermissionAny('hg.admin', 'hg.create.repository')():
 
            #you're not super admin nor have global create permissions,
 
            #but maybe you have at least write permission to a parent group ?
 
            _gr = RepoGroup.get(parent_group)
 
            gr_name = _gr.group_name if _gr else None
 
            if not HasReposGroupPermissionAny('group.admin', 'group.write')(group_name=gr_name):
 
                raise HTTPForbidden
 

	
 
        GET /repos/new: Form to create a new item
 
        """
 
        acl_groups = GroupList(RepoGroup.query().all(),
 
                               perm_set=['group.write', 'group.admin'])
 
        c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
 
        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
 
        choices, c.landing_revs = ScmModel().get_repo_landing_revs()
 

	
 
        parent_group = request.GET.get('parent_group')
 
        self.__load_defaults()
 
        c.new_repo = repo_name_slug(new_repo)
 

	
 
        ## apply the defaults from defaults page
 
        defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
 
        if parent_group:
 
@@ -225,7 +236,7 @@ class ReposController(BaseRepoController
 
            encoding="UTF-8"
 
        )
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def update(self, repo_name):
 
        """
 
        PUT /repos/repo_name: Update an existing item"""
 
@@ -273,7 +284,7 @@ class ReposController(BaseRepoController
 
                    % repo_name, category='error')
 
        return redirect(url('edit_repo', repo_name=changed_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def delete(self, repo_name):
 
        """
 
        DELETE /repos/repo_name: Delete an existing item"""
 
@@ -405,7 +416,7 @@ class ReposController(BaseRepoController
 
                    category='error')
 
            raise HTTPInternalServerError()
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def repo_stats(self, repo_name):
 
        """
 
        DELETE an existing repository statistics
 
@@ -422,7 +433,7 @@ class ReposController(BaseRepoController
 
                    category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def repo_cache(self, repo_name):
 
        """
 
        INVALIDATE existing repository cache
 
@@ -439,7 +450,7 @@ class ReposController(BaseRepoController
 
                    category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def repo_locking(self, repo_name):
 
        """
 
        Unlock repository when it is locked !
 
@@ -459,7 +470,34 @@ class ReposController(BaseRepoController
 
                    category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def toggle_locking(self, repo_name):
 
        """
 
        Toggle locking of repository by simple GET call to url
 

	
 
        :param repo_name:
 
        """
 

	
 
        try:
 
            repo = Repository.get_by_repo_name(repo_name)
 

	
 
            if repo.enable_locking:
 
                if repo.locked[0]:
 
                    Repository.unlock(repo)
 
                    action = _('unlocked')
 
                else:
 
                    Repository.lock(repo, c.rhodecode_user.user_id)
 
                    action = _('locked')
 

	
 
                h.flash(_('Repository has been %s') % action,
 
                        category='success')
 
        except Exception, e:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during unlocking'),
 
                    category='error')
 
        return redirect(url('summary_home', repo_name=repo_name))
 

	
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def repo_public_journal(self, repo_name):
 
        """
 
        Set's this repository to be visible in public journal,
 
@@ -487,7 +525,7 @@ class ReposController(BaseRepoController
 
            h.flash(_('Token mismatch'), category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def repo_pull(self, repo_name):
 
        """
 
        Runs task to update given repository with remote changes,
 
@@ -504,7 +542,7 @@ class ReposController(BaseRepoController
 

	
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def repo_as_fork(self, repo_name):
 
        """
 
        Mark given repository as a fork of another
 
@@ -531,7 +569,7 @@ class ReposController(BaseRepoController
 
        """GET /repos/repo_name: Show a specific item"""
 
        # url('repo', repo_name=ID)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    @HasRepoPermissionAllDecorator('repository.admin')
 
    def edit(self, repo_name, format='html'):
 
        """GET /repos/repo_name/edit: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
rhodecode/controllers/admin/settings.py
Show inline comments
 
@@ -491,40 +491,6 @@ class SettingsController(BaseController)
 

	
 
        return render('admin/users/user_edit_my_account_pullrequests.html')
 

	
 
    @NotAnonymous()
 
    def create_repository(self):
 
        """GET /_admin/create_repository: Form to create a new item"""
 
        new_repo = request.GET.get('repo', '')
 
        parent_group = request.GET.get('parent_group')
 
        if not HasPermissionAny('hg.admin', 'hg.create.repository')():
 
            #you're not super admin nor have global create permissions,
 
            #but maybe you have at least write permission to a parent group ?
 
            _gr = RepoGroup.get(parent_group)
 
            gr_name = _gr.group_name if _gr else None
 
            if not HasReposGroupPermissionAny('group.admin', 'group.write')(group_name=gr_name):
 
                raise HTTPForbidden
 

	
 
        acl_groups = GroupList(RepoGroup.query().all(),
 
                               perm_set=['group.write', 'group.admin'])
 
        c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
 
        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
 
        choices, c.landing_revs = ScmModel().get_repo_landing_revs()
 

	
 
        c.new_repo = repo_name_slug(new_repo)
 

	
 
        ## apply the defaults from defaults page
 
        defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
 
        if parent_group:
 
            defaults.update({'repo_group': parent_group})
 

	
 
        return htmlfill.render(
 
            render('admin/repos/repo_add.html'),
 
            defaults=defaults,
 
            errors={},
 
            prefix_error=False,
 
            encoding="UTF-8"
 
        )
 

	
 
    def _get_hg_ui_settings(self):
 
        ret = RhodeCodeUi.query().all()
 

	
rhodecode/controllers/settings.py
Show inline comments
 
deleted file
rhodecode/model/forms.py
Show inline comments
 
@@ -227,27 +227,6 @@ def RepoFieldForm():
 
    return _RepoFieldForm
 

	
 

	
 
def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
                     repo_groups=[], landing_revs=[]):
 
    class _RepoForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
 
                        v.SlugifyName())
 
        repo_group = All(v.CanWriteGroup(old_data),
 
                         v.OneOf(repo_groups, hideList=True))
 
        repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
 
        repo_private = v.StringBoolean(if_missing=False)
 
        repo_landing_rev = v.OneOf(landing_revs, hideList=True)
 
        clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
 

	
 
        chained_validators = [v.ValidCloneUri(),
 
                              v.ValidRepoName(edit, old_data),
 
                              v.ValidPerms(),
 
                              v.ValidSettings()]
 
    return _RepoForm
 

	
 

	
 
def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
                 repo_groups=[], landing_revs=[]):
 
    class _RepoForkForm(formencode.Schema):
rhodecode/model/repo.py
Show inline comments
 
@@ -297,7 +297,13 @@ class RepoModel(BaseModel):
 

	
 
            new_name = cur_repo.get_new_name(kwargs['repo_name'])
 
            cur_repo.repo_name = new_name
 
            #if private flag is set, reset default permission to NONE
 

	
 
            if kwargs.get('repo_private'):
 
                EMPTY_PERM = 'repository.none'
 
                RepoModel().grant_user_permission(
 
                    repo=cur_repo, user='default', perm=EMPTY_PERM
 
                )
 
            #handle extra fields
 
            for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
 
                k = RepositoryField.un_prefix_key(field)
rhodecode/model/validators.py
Show inline comments
 
@@ -16,7 +16,7 @@ from formencode.validators import (
 
from rhodecode.lib.compat import OrderedSet
 
from rhodecode.lib import ipaddr
 
from rhodecode.lib.utils import repo_name_slug
 
from rhodecode.lib.utils2 import safe_int
 
from rhodecode.lib.utils2 import safe_int, str2bool
 
from rhodecode.model.db import RepoGroup, Repository, UserGroup, User,\
 
    ChangesetStatus
 
from rhodecode.lib.exceptions import LdapImportError
 
@@ -591,14 +591,11 @@ def ValidPerms(type_='repo'):
 
                         'g': 'users_group'
 
                    }[k[0]]
 
                    if member == 'default':
 
                        if value.get('repo_private'):
 
                        if str2bool(value.get('repo_private')):
 
                            # set none for default when updating to
 
                            # private repo
 
                            # private repo protects agains form manipulation
 
                            v = EMPTY_PERM
 
                    perms_update.add((member, v, t))
 
            #always set NONE when private flag is set
 
            if value.get('repo_private'):
 
                perms_update.add(('default', EMPTY_PERM, 'user'))
 

	
 
            value['perms_updates'] = list(perms_update)
 
            value['perms_new'] = list(perms_new)
rhodecode/templates/admin/repos/repo_edit.html
Show inline comments
 
@@ -165,18 +165,19 @@ ${self.context_bar('options')}
 
                    <label for="input">${_('Permissions')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.hidden('repo_private')}
 
                    <%include file="repo_edit_perms.html"/>
 
                </div>
 
            </div>
 
            <div class="buttons">
 
              ${h.submit('save',_('Save'),class_="ui-btn large")}
 
              ${h.reset('reset',_('Reset'),class_="ui-btn large")}
 
            </div>            
 
            </div>
 
       </div>
 
    </div>
 
    ${h.end_form()} 
 
    ${h.end_form()}
 
</div>
 
          
 

	
 

	
 
<div class="box box-right"  style="clear:right">
 
    <div class="title">
rhodecode/templates/base/base.html
Show inline comments
 
@@ -116,11 +116,7 @@
 
          <a href="#" class="dropdown options"></span>${_('Options')}</a>
 
          <ul>
 
             %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
 
               %if h.HasPermissionAll('hg.admin')('access settings on repository'):
 
                   <li>${h.link_to(_('Settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
 
               %else:
 
                   <li>${h.link_to(_('Settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
 
               %endif
 
             %endif
 
              %if c.rhodecode_db_repo.fork:
 
               <li>${h.link_to(_('Compare fork'),h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,org_ref_type='branch',org_ref='default',other_repo=c.repo_name,other_ref_type='branch',other_ref=request.GET.get('branch') or 'default', merge=1),class_='compare_request')}</li>
rhodecode/templates/data_table/_dt_elements.html
Show inline comments
 
@@ -113,26 +113,14 @@
 
<%def name="repo_actions(repo_name, super_user=True)">
 
  <div>
 
    <div style="float:left">
 
    %if super_user:
 
      <a href="${h.url('edit_repo',repo_name=repo_name)}" title="${_('edit')}">
 
        ${h.submit('edit_%s' % repo_name,_('edit'),class_="edit_icon action_button")}
 
      </a>
 
    %else:
 
      <a href="${h.url('repo_settings_home',repo_name=repo_name)}" title="${_('edit')}">
 
        ${h.submit('edit_%s' % repo_name,_('edit'),class_="edit_icon action_button")}
 
      </a>
 
    %endif
 
    </div>
 
    <div style="float:left">
 
    %if super_user:
 
      ${h.form(h.url('repo', repo_name=repo_name),method='delete')}
 
        ${h.submit('remove_%s' % repo_name,_('delete'),class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
 
      ${h.end_form()}
 
    %else:
 
      ${h.form(h.url('repo_settings_delete', repo_name=repo_name),method='delete')}
 
        ${h.submit('remove_%s' % repo_name,_('delete'),class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
 
      ${h.end_form()}
 
    %endif
 
    </div>
 
  </div>
 
</%def>
rhodecode/templates/settings/repo_settings.html
Show inline comments
 
deleted file
rhodecode/templates/summary/summary.html
Show inline comments
 
@@ -179,11 +179,7 @@ ${self.context_bar('summary')}
 

	
 
             %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
 
             <li>
 
              %if h.HasPermissionAll('hg.admin')('access settings on repository'):
 
                  ${h.link_to(_('Settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}
 
              %else:
 
                  ${h.link_to(_('Settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}
 
              %endif
 
            </li>
 
            %endif
 

	
rhodecode/tests/functional/test_admin_repos.py
Show inline comments
 
@@ -4,10 +4,21 @@ import os
 
import urllib
 

	
 
from rhodecode.lib import vcs
 
from rhodecode.model.db import Repository, RepoGroup
 
from rhodecode.model.db import Repository, RepoGroup, UserRepoToPerm, User,\
 
    Permission
 
from rhodecode.tests import *
 
from rhodecode.model.repos_group import ReposGroupModel
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.meta import Session
 

	
 

	
 
def _get_permission_for_user(user, repo):
 
    perm = UserRepoToPerm.query()\
 
                .filter(UserRepoToPerm.repository ==
 
                        Repository.get_by_repo_name(repo))\
 
                .filter(UserRepoToPerm.user == User.get_by_username(user))\
 
                .all()
 
    return perm
 

	
 

	
 
class TestAdminReposController(TestController):
 
@@ -200,13 +211,6 @@ class TestAdminReposController(TestContr
 
        except:
 
            self.fail('no repo %s in filesystem' % repo_name)
 

	
 
    def test_new(self):
 
        self.log_user()
 
        response = self.app.get(url('new_repo'))
 

	
 
    def test_new_as_xml(self):
 
        response = self.app.get(url('formatted_new_repo', format='xml'))
 

	
 
    def test_update(self):
 
        response = self.app.put(url('repo', repo_name=HG_REPO))
 

	
 
@@ -328,3 +332,42 @@ class TestAdminReposController(TestContr
 

	
 
    def test_edit(self):
 
        response = self.app.get(url('edit_repo', repo_name=HG_REPO))
 

	
 
    def test_set_private_flag_sets_default_to_none(self):
 
        self.log_user()
 
        #initially repository perm should be read
 
        perm = _get_permission_for_user(user='default', repo=HG_REPO)
 
        self.assertTrue(len(perm), 1)
 
        self.assertEqual(perm[0].permission.permission_name, 'repository.read')
 
        self.assertEqual(Repository.get_by_repo_name(HG_REPO).private, False)
 

	
 
        response = self.app.put(url('repo', repo_name=HG_REPO),
 
                        _get_repo_create_params(repo_private=1,
 
                                                repo_name=HG_REPO,
 
                                                user=TEST_USER_ADMIN_LOGIN))
 
        self.checkSessionFlash(response,
 
                               msg='Repository %s updated successfully' % (HG_REPO))
 
        self.assertEqual(Repository.get_by_repo_name(HG_REPO).private, True)
 

	
 
        #now the repo default permission should be None
 
        perm = _get_permission_for_user(user='default', repo=HG_REPO)
 
        self.assertTrue(len(perm), 1)
 
        self.assertEqual(perm[0].permission.permission_name, 'repository.none')
 

	
 
        response = self.app.put(url('repo', repo_name=HG_REPO),
 
                        _get_repo_create_params(repo_private=False,
 
                                                repo_name=HG_REPO,
 
                                                user=TEST_USER_ADMIN_LOGIN))
 
        self.checkSessionFlash(response,
 
                               msg='Repository %s updated successfully' % (HG_REPO))
 
        self.assertEqual(Repository.get_by_repo_name(HG_REPO).private, False)
 

	
 
        #we turn off private now the repo default permission should stay None
 
        perm = _get_permission_for_user(user='default', repo=HG_REPO)
 
        self.assertTrue(len(perm), 1)
 
        self.assertEqual(perm[0].permission.permission_name, 'repository.none')
 

	
 
        #update this permission back
 
        perm[0].permission = Permission.get_by_key('repository.read')
 
        Session().add(perm[0])
 
        Session().commit()
rhodecode/tests/functional/test_settings.py
Show inline comments
 
deleted file
0 comments (0 inline, 0 general)