core: moved goto_switcher views into pyramid.

This commit is contained in:
Marcin Kuzminski 2017-04-19 15:12:58 +02:00
parent d3041b73d6
commit e6137d85f4
8 changed files with 263 additions and 263 deletions

View file

@ -33,5 +33,9 @@ def includeme(config):
name='repo_list_data',
pattern='/_repos')
config.add_route(
name='goto_switcher_data',
pattern='/_goto_data')
# Scan module for configuration decorators.
config.scan()

View file

@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016-2017 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# 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 Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import json
import pytest
from . import assert_and_get_content
from rhodecode.tests import TestController, TEST_USER_ADMIN_LOGIN
from rhodecode.tests.fixture import Fixture
from rhodecode.lib.utils import map_groups
from rhodecode.model.repo import RepoModel
from rhodecode.model.repo_group import RepoGroupModel
from rhodecode.model.db import Session, Repository, RepoGroup
fixture = Fixture()
def route_path(name, params=None, **kwargs):
import urllib
base_url = {
'goto_switcher_data': '/_goto_data',
}[name].format(**kwargs)
if params:
base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
return base_url
class TestGotoSwitcherData(TestController):
required_repos_with_groups = [
'abc',
'abc-fork',
'forks/abcd',
'abcd',
'abcde',
'a/abc',
'aa/abc',
'aaa/abc',
'aaaa/abc',
'repos_abc/aaa/abc',
'abc_repos/abc',
'abc_repos/abcd',
'xxx/xyz',
'forked-abc/a/abc'
]
@pytest.fixture(autouse=True, scope='class')
def prepare(self, request, pylonsapp):
for repo_and_group in self.required_repos_with_groups:
# create structure of groups and return the last group
repo_group = map_groups(repo_and_group)
RepoModel()._create_repo(
repo_and_group, 'hg', 'test-ac', TEST_USER_ADMIN_LOGIN,
repo_group=getattr(repo_group, 'group_id', None))
Session().commit()
request.addfinalizer(self.cleanup)
def cleanup(self):
# first delete all repos
for repo_and_groups in self.required_repos_with_groups:
repo = Repository.get_by_repo_name(repo_and_groups)
if repo:
RepoModel().delete(repo)
Session().commit()
# then delete all empty groups
for repo_and_groups in self.required_repos_with_groups:
if '/' in repo_and_groups:
r_group = repo_and_groups.rsplit('/', 1)[0]
repo_group = RepoGroup.get_by_group_name(r_group)
if not repo_group:
continue
parents = repo_group.parents
RepoGroupModel().delete(repo_group, force_delete=True)
Session().commit()
for el in reversed(parents):
RepoGroupModel().delete(el, force_delete=True)
Session().commit()
def test_returns_list_of_repos_and_groups(self, xhr_header):
self.log_user()
response = self.app.get(
route_path('goto_switcher_data'),
extra_environ=xhr_header, status=200)
result = json.loads(response.body)['results']
repos, groups, commits = assert_and_get_content(result)
assert len(repos) == len(Repository.get_all())
assert len(groups) == len(RepoGroup.get_all())
assert len(commits) == 0
def test_returns_list_of_repos_and_groups_filtered(self, xhr_header):
self.log_user()
response = self.app.get(
route_path('goto_switcher_data'),
params={'query': 'abc'},
extra_environ=xhr_header, status=200)
result = json.loads(response.body)['results']
repos, groups, commits = assert_and_get_content(result)
assert len(repos) == 13
assert len(groups) == 5
assert len(commits) == 0
def test_returns_list_of_properly_sorted_and_filtered(self, xhr_header):
self.log_user()
response = self.app.get(
route_path('goto_switcher_data'),
params={'query': 'abc'},
extra_environ=xhr_header, status=200)
result = json.loads(response.body)['results']
repos, groups, commits = assert_and_get_content(result)
test_repos = [x['text'] for x in repos[:4]]
assert ['abc', 'abcd', 'a/abc', 'abcde'] == test_repos
test_groups = [x['text'] for x in groups[:4]]
assert ['abc_repos', 'repos_abc',
'forked-abc', 'forked-abc/a'] == test_groups

View file

@ -18,6 +18,7 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import re
import logging
from pyramid.view import view_config
@ -25,8 +26,9 @@ from pyramid.view import view_config
from rhodecode.apps._base import BaseAppView
from rhodecode.lib import helpers as h
from rhodecode.lib.auth import LoginRequired, NotAnonymous
from rhodecode.lib.index import searcher_from_config
from rhodecode.lib.utils2 import safe_unicode, str2bool
from rhodecode.model.db import func, Repository
from rhodecode.model.db import func, Repository, RepoGroup
from rhodecode.model.repo import RepoModel
from rhodecode.model.scm import ScmModel
@ -111,6 +113,57 @@ class HomeView(BaseAppView):
}
for obj in repo_iter]
def _get_repo_group_list(self, name_contains=None, limit=20):
query = RepoGroup.query()\
.order_by(func.length(RepoGroup.group_name))\
.order_by(RepoGroup.group_name)
if name_contains:
ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
query = query.filter(
RepoGroup.group_name.ilike(ilike_expression))
query = query.limit(limit)
all_groups = query.all()
repo_groups_iter = ScmModel().get_repo_groups(all_groups)
return [
{
'id': obj.group_name,
'text': obj.group_name,
'type': 'group',
'obj': {},
'url': h.url('repo_group_home', group_name=obj.group_name)
}
for obj in repo_groups_iter]
def _get_hash_commit_list(self, auth_user, hash_starts_with=None):
if not hash_starts_with or len(hash_starts_with) < 3:
return []
commit_hashes = re.compile('([0-9a-f]{2,40})').findall(hash_starts_with)
if len(commit_hashes) != 1:
return []
commit_hash_prefix = commit_hashes[0]
searcher = searcher_from_config(self.request.registry.settings)
result = searcher.search(
'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user,
raise_on_exc=False)
return [
{
'id': entry['commit_id'],
'text': entry['commit_id'],
'type': 'commit',
'obj': {'repo': entry['repository']},
'url': h.url('changeset_home',
repo_name=entry['repository'],
revision=entry['commit_id'])
}
for entry in result['results']]
@LoginRequired()
@view_config(
route_name='repo_list_data', request_method='GET',
@ -136,3 +189,49 @@ class HomeView(BaseAppView):
'results': res
}
return data
@LoginRequired()
@view_config(
route_name='goto_switcher_data', request_method='GET',
renderer='json_ext', xhr=True)
def goto_switcher_data(self):
c = self.load_default_context()
_ = self.request.translate
query = self.request.GET.get('query')
log.debug('generating goto switcher list, query %s', query)
res = []
repo_groups = self._get_repo_group_list(query)
if repo_groups:
res.append({
'text': _('Groups'),
'children': repo_groups
})
repos = self._get_repo_list(query)
if repos:
res.append({
'text': _('Repositories'),
'children': repos
})
commits = self._get_hash_commit_list(c.auth_user, query)
if commits:
unique_repos = {}
for commit in commits:
unique_repos.setdefault(commit['obj']['repo'], []
).append(commit)
for repo in unique_repos:
res.append({
'text': _('Commits in %(repo)s') % {'repo': repo},
'children': unique_repos[repo]
})
data = {
'more': False,
'results': res
}
return data

View file

@ -188,8 +188,6 @@ def make_map(config):
# MAIN PAGE
rmap.connect('home', '/', controller='home', action='index', jsroute=True)
rmap.connect('goto_switcher_data', '/_goto_data', controller='home',
action='goto_switcher_data')
# TODO: johbo: Static links, to be replaced by our redirection mechanism
rmap.connect('rst_help',

View file

@ -24,20 +24,15 @@ Home controller for RhodeCode Enterprise
import logging
import time
import re
from pylons import tmpl_context as c, request, url, config
from pylons.i18n.translation import _
from sqlalchemy.sql import func
from pylons import tmpl_context as c
from rhodecode.lib.auth import (
LoginRequired, HasPermissionAllDecorator, AuthUser,
HasRepoGroupPermissionAnyDecorator, XHRRequired)
LoginRequired, HasPermissionAllDecorator,
HasRepoGroupPermissionAnyDecorator)
from rhodecode.lib.base import BaseController, render
from rhodecode.lib.index import searcher_from_config
from rhodecode.lib.ext_json import json
from rhodecode.lib.utils import jsonify
from rhodecode.lib.utils2 import safe_unicode, str2bool
from rhodecode.model.db import Repository, RepoGroup
from rhodecode.model.repo import RepoModel
from rhodecode.model.repo_group import RepoGroupModel
@ -113,123 +108,3 @@ class HomeController(BaseController):
c.repo_groups_data = json.dumps(repo_group_data)
return render('index_repo_group.mako')
def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
query = Repository.query()\
.order_by(func.length(Repository.repo_name))\
.order_by(Repository.repo_name)
if repo_type:
query = query.filter(Repository.repo_type == repo_type)
if name_contains:
ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
query = query.filter(
Repository.repo_name.ilike(ilike_expression))
query = query.limit(limit)
all_repos = query.all()
repo_iter = self.scm_model.get_repos(all_repos)
return [
{
'id': obj['name'],
'text': obj['name'],
'type': 'repo',
'obj': obj['dbrepo'],
'url': url('summary_home', repo_name=obj['name'])
}
for obj in repo_iter]
def _get_repo_group_list(self, name_contains=None, limit=20):
query = RepoGroup.query()\
.order_by(func.length(RepoGroup.group_name))\
.order_by(RepoGroup.group_name)
if name_contains:
ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
query = query.filter(
RepoGroup.group_name.ilike(ilike_expression))
query = query.limit(limit)
all_groups = query.all()
repo_groups_iter = self.scm_model.get_repo_groups(all_groups)
return [
{
'id': obj.group_name,
'text': obj.group_name,
'type': 'group',
'obj': {},
'url': url('repo_group_home', group_name=obj.group_name)
}
for obj in repo_groups_iter]
def _get_hash_commit_list(self, hash_starts_with=None, limit=20):
if not hash_starts_with or len(hash_starts_with) < 3:
return []
commit_hashes = re.compile('([0-9a-f]{2,40})').findall(hash_starts_with)
if len(commit_hashes) != 1:
return []
commit_hash_prefix = commit_hashes[0]
auth_user = AuthUser(
user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
searcher = searcher_from_config(config)
result = searcher.search(
'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user,
raise_on_exc=False)
return [
{
'id': entry['commit_id'],
'text': entry['commit_id'],
'type': 'commit',
'obj': {'repo': entry['repository']},
'url': url('changeset_home',
repo_name=entry['repository'],
revision=entry['commit_id'])
}
for entry in result['results']]
@LoginRequired()
@XHRRequired()
@jsonify
def goto_switcher_data(self):
query = request.GET.get('query')
log.debug('generating goto switcher list, query %s', query)
res = []
repo_groups = self._get_repo_group_list(query)
if repo_groups:
res.append({
'text': _('Groups'),
'children': repo_groups
})
repos = self._get_repo_list(query)
if repos:
res.append({
'text': _('Repositories'),
'children': repos
})
commits = self._get_hash_commit_list(query)
if commits:
unique_repos = {}
for commit in commits:
unique_repos.setdefault(commit['obj']['repo'], []
).append(commit)
for repo in unique_repos:
res.append({
'text': _('Commits in %(repo)s') % {'repo': repo},
'children': unique_repos[repo]
})
data = {
'more': False,
'results': res
}
return data

View file

@ -96,6 +96,7 @@ function registerRCRoutes() {
pyroutes.register('user_autocomplete_data', '/_users', []);
pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
pyroutes.register('repo_list_data', '/_repos', []);
pyroutes.register('goto_switcher_data', '/_goto_data', []);
pyroutes.register('repo_maintenance', '/%(repo_name)s/maintenance', ['repo_name']);
pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/maintenance/execute', ['repo_name']);
pyroutes.register('strip', '/%(repo_name)s/strip', ['repo_name']);

View file

@ -503,7 +503,7 @@
query.callback({results: cachedData.results});
} else {
$.ajax({
url: "${h.url('goto_switcher_data')}",
url: pyroutes.url('goto_switcher_data'),
data: {'query': query.term},
dataType: 'json',
type: 'GET',

View file

@ -18,20 +18,17 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import json
from mock import patch
import pytest
from pylons import tmpl_context as c
import rhodecode
from rhodecode.lib.utils import map_groups
from rhodecode.model.db import Repository, User, RepoGroup
from rhodecode.model.db import Repository, User
from rhodecode.model.meta import Session
from rhodecode.model.repo import RepoModel
from rhodecode.model.repo_group import RepoGroupModel
from rhodecode.model.settings import SettingsModel
from rhodecode.tests import TestController, url, TEST_USER_ADMIN_LOGIN
from rhodecode.tests import TestController, url
from rhodecode.tests.fixture import Fixture
@ -130,128 +127,3 @@ class TestHomeController(TestController):
response.mustcontain(version_string)
if state is False:
response.mustcontain(no=[version_string])
def assert_and_get_content(result):
repos = []
groups = []
commits = []
for data in result:
for data_item in data['children']:
assert data_item['id']
assert data_item['text']
assert data_item['url']
if data_item['type'] == 'repo':
repos.append(data_item)
elif data_item['type'] == 'group':
groups.append(data_item)
elif data_item['type'] == 'commit':
commits.append(data_item)
else:
raise Exception('invalid type %s' % data_item['type'])
return repos, groups, commits
class TestGotoSwitcherData(TestController):
required_repos_with_groups = [
'abc',
'abc-fork',
'forks/abcd',
'abcd',
'abcde',
'a/abc',
'aa/abc',
'aaa/abc',
'aaaa/abc',
'repos_abc/aaa/abc',
'abc_repos/abc',
'abc_repos/abcd',
'xxx/xyz',
'forked-abc/a/abc'
]
@pytest.fixture(autouse=True, scope='class')
def prepare(self, request, pylonsapp):
for repo_and_group in self.required_repos_with_groups:
# create structure of groups and return the last group
repo_group = map_groups(repo_and_group)
RepoModel()._create_repo(
repo_and_group, 'hg', 'test-ac', TEST_USER_ADMIN_LOGIN,
repo_group=getattr(repo_group, 'group_id', None))
Session().commit()
request.addfinalizer(self.cleanup)
def cleanup(self):
# first delete all repos
for repo_and_groups in self.required_repos_with_groups:
repo = Repository.get_by_repo_name(repo_and_groups)
if repo:
RepoModel().delete(repo)
Session().commit()
# then delete all empty groups
for repo_and_groups in self.required_repos_with_groups:
if '/' in repo_and_groups:
r_group = repo_and_groups.rsplit('/', 1)[0]
repo_group = RepoGroup.get_by_group_name(r_group)
if not repo_group:
continue
parents = repo_group.parents
RepoGroupModel().delete(repo_group, force_delete=True)
Session().commit()
for el in reversed(parents):
RepoGroupModel().delete(el, force_delete=True)
Session().commit()
def test_returns_list_of_repos_and_groups(self):
self.log_user()
response = self.app.get(
url(controller='home', action='goto_switcher_data'),
headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
result = json.loads(response.body)['results']
repos, groups, commits = assert_and_get_content(result)
assert len(repos) == len(Repository.get_all())
assert len(groups) == len(RepoGroup.get_all())
assert len(commits) == 0
def test_returns_list_of_repos_and_groups_filtered(self):
self.log_user()
response = self.app.get(
url(controller='home', action='goto_switcher_data'),
headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
params={'query': 'abc'}, status=200)
result = json.loads(response.body)['results']
repos, groups, commits = assert_and_get_content(result)
assert len(repos) == 13
assert len(groups) == 5
assert len(commits) == 0
def test_returns_list_of_properly_sorted_and_filtered(self):
self.log_user()
response = self.app.get(
url(controller='home', action='goto_switcher_data'),
headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
params={'query': 'abc'}, status=200)
result = json.loads(response.body)['results']
repos, groups, commits = assert_and_get_content(result)
test_repos = [x['text'] for x in repos[:4]]
assert ['abc', 'abcd', 'a/abc', 'abcde'] == test_repos
test_groups = [x['text'] for x in groups[:4]]
assert ['abc_repos', 'repos_abc',
'forked-abc', 'forked-abc/a'] == test_groups