tags/branches/bookmarks: moved views into pyramid.

This commit is contained in:
Marcin Kuzminski 2017-05-12 16:23:26 +02:00
parent ddf67dbb5b
commit ca6ba228c3
14 changed files with 264 additions and 223 deletions

View file

@ -24,8 +24,10 @@ from pylons import tmpl_context as c
from pyramid.httpexceptions import HTTPFound
from rhodecode.lib import helpers as h
from rhodecode.lib.utils2 import StrictAttributeDict, safe_int
from rhodecode.lib.utils import PartialRenderer
from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time
from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
from rhodecode.lib.ext_json import json
from rhodecode.model import repo
from rhodecode.model.db import User
from rhodecode.model.scm import ScmModel
@ -37,6 +39,24 @@ ADMIN_PREFIX = '/_admin'
STATIC_FILE_PREFIX = '/_static'
def get_format_ref_id(repo):
"""Returns a `repo` specific reference formatter function"""
if h.is_svn(repo):
return _format_ref_id_svn
else:
return _format_ref_id
def _format_ref_id(name, raw_id):
"""Default formatting of a given reference `name`"""
return name
def _format_ref_id_svn(name, raw_id):
"""Special way of formatting a reference for Subversion including path"""
return '%s@%s' % (name, raw_id)
class TemplateArgs(StrictAttributeDict):
pass
@ -170,6 +190,56 @@ class DataGridAppView(object):
return draw, start, length
class BaseReferencesView(RepoAppView):
"""
Base for reference view for branches, tags and bookmarks.
"""
def load_default_context(self):
c = self._get_local_tmpl_context()
# TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
c.repo_info = self.db_repo
self._register_global_c(c)
return c
def load_refs_context(self, ref_items, partials_template):
_render = PartialRenderer(partials_template)
_data = []
pre_load = ["author", "date", "message"]
is_svn = h.is_svn(self.rhodecode_vcs_repo)
format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
for ref_name, commit_id in ref_items:
commit = self.rhodecode_vcs_repo.get_commit(
commit_id=commit_id, pre_load=pre_load)
# TODO: johbo: Unify generation of reference links
use_commit_id = '/' in ref_name or is_svn
files_url = h.url(
'files_home',
repo_name=c.repo_name,
f_path=ref_name if is_svn else '',
revision=commit_id if use_commit_id else ref_name,
at=ref_name)
_data.append({
"name": _render('name', ref_name, files_url),
"name_raw": ref_name,
"date": _render('date', commit.date),
"date_raw": datetime_to_time(commit.date),
"author": _render('author', commit.author),
"commit": _render(
'commit', commit.message, commit.raw_id, commit.idx),
"commit_raw": commit.idx,
"compare": _render(
'compare', format_ref_id(ref_name, commit.raw_id)),
})
c.has_references = bool(_data)
c.data = json.dumps(_data)
class RepoRoutePredicate(object):
def __init__(self, val, config):
self.val = val

View file

@ -21,6 +21,21 @@
def includeme(config):
# Tags
config.add_route(
name='tags_home',
pattern='/{repo_name:.*?[^/]}/tags', repo_route=True)
# Branches
config.add_route(
name='branches_home',
pattern='/{repo_name:.*?[^/]}/branches', repo_route=True)
# Bookmarks
config.add_route(
name='bookmarks_home',
pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True)
# Settings
config.add_route(
name='edit_repo',

View file

@ -18,24 +18,35 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import pytest
from rhodecode.model.db import Repository
from rhodecode.tests import *
class TestBookmarksController(TestController):
def route_path(name, params=None, **kwargs):
import urllib
base_url = {
'bookmarks_home': '/{repo_name}/bookmarks',
}[name].format(**kwargs)
if params:
base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
return base_url
@pytest.mark.usefixtures('autologin_user', 'app')
class TestBookmarks(object):
def test_index(self, backend):
self.log_user()
if backend.alias == 'hg':
response = self.app.get(url(controller='bookmarks',
action='index',
repo_name=backend.repo_name))
response = self.app.get(
route_path('bookmarks_home', repo_name=backend.repo_name))
repo = Repository.get_by_repo_name(backend.repo_name)
for commit_id, obj_name in repo.scm_instance().bookmarks.items():
assert commit_id in response
assert obj_name in response
else:
self.app.get(url(controller='bookmarks',
action='index',
repo_name=backend.repo_name), status=404)
self.app.get(
route_path('bookmarks_home', repo_name=backend.repo_name),
status=404)

View file

@ -18,17 +18,28 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import pytest
from rhodecode.model.db import Repository
from rhodecode.tests import *
class TestBranchesController(TestController):
def route_path(name, params=None, **kwargs):
import urllib
base_url = {
'branches_home': '/{repo_name}/branches',
}[name].format(**kwargs)
if params:
base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
return base_url
@pytest.mark.usefixtures('autologin_user', 'app')
class TestBranchesController(object):
def test_index(self, backend):
self.log_user()
response = self.app.get(url(controller='branches',
action='index',
repo_name=backend.repo_name))
response = self.app.get(
route_path('branches_home', repo_name=backend.repo_name))
repo = Repository.get_by_repo_name(backend.repo_name)

View file

@ -18,16 +18,27 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import pytest
from rhodecode.model.db import Repository
from rhodecode.tests import *
class TestTagsController(TestController):
def route_path(name, params=None, **kwargs):
import urllib
base_url = {
'tags_home': '/{repo_name}/tags',
}[name].format(**kwargs)
if params:
base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
return base_url
@pytest.mark.usefixtures('autologin_user', 'app')
class TestTagsController(object):
def test_index(self, backend):
self.log_user()
response = self.app.get(url(controller='tags',
action='index',
repo_name=backend.repo_name))
response = self.app.get(
route_path('tags_home', repo_name=backend.repo_name))
repo = Repository.get_by_repo_name(backend.repo_name)

View file

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2011-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 logging
from pyramid.httpexceptions import HTTPNotFound
from pyramid.view import view_config
from rhodecode.apps._base import BaseReferencesView
from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator)
from rhodecode.lib import helpers as h
log = logging.getLogger(__name__)
class RepoBookmarksView(BaseReferencesView):
@LoginRequired()
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='bookmarks_home', request_method='GET',
renderer='rhodecode:templates/bookmarks/bookmarks.mako')
def bookmarks(self):
c = self.load_default_context()
if not h.is_hg(self.db_repo):
raise HTTPNotFound()
ref_items = self.rhodecode_vcs_repo.bookmarks.items()
self.load_refs_context(
ref_items=ref_items, partials_template='bookmarks/bookmarks_data.mako')
return self._get_template_context(c)

View file

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2011-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 logging
from pyramid.view import view_config
from rhodecode.apps._base import BaseReferencesView
from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator)
log = logging.getLogger(__name__)
class RepoBranchesView(BaseReferencesView):
@LoginRequired()
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='branches_home', request_method='GET',
renderer='rhodecode:templates/branches/branches.mako')
def branches(self):
c = self.load_default_context()
c.closed_branches = self.rhodecode_vcs_repo.branches_closed
# NOTE(marcink):
# we need this trick because of PartialRenderer still uses the
# global 'c', we might not need this after full pylons migration
self._register_global_c(c)
ref_items = self.rhodecode_vcs_repo.branches_all.items()
self.load_refs_context(
ref_items=ref_items, partials_template='branches/branches_data.mako')
return self._get_template_context(c)

View file

@ -17,30 +17,29 @@
# 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/
"""
Bookmarks controller for rhodecode
"""
import logging
from pyramid.view import view_config
from pylons import tmpl_context as c
from webob.exc import HTTPNotFound
from rhodecode.controllers.base_references import BaseReferencesController
from rhodecode.lib import helpers as h
from rhodecode.apps._base import BaseReferencesView
from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator)
log = logging.getLogger(__name__)
class BookmarksController(BaseReferencesController):
class RepoTagsView(BaseReferencesView):
partials_template = 'bookmarks/bookmarks_data.mako'
template = 'bookmarks/bookmarks.mako'
@LoginRequired()
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='tags_home', request_method='GET',
renderer='rhodecode:templates/tags/tags.mako')
def tags(self):
c = self.load_default_context()
def __before__(self):
super(BookmarksController, self).__before__()
if not h.is_hg(c.rhodecode_repo):
raise HTTPNotFound()
ref_items = self.rhodecode_vcs_repo.tags.items()
self.load_refs_context(
ref_items=ref_items, partials_template='tags/tags_data.mako')
def _get_reference_items(self, repo):
return repo.bookmarks.items()
return self._get_template_context(c)

View file

@ -890,18 +890,6 @@ def make_map(config):
controller='summary', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('branches_home', '/{repo_name}/branches',
controller='branches', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('tags_home', '/{repo_name}/tags',
controller='tags', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('bookmarks_home', '/{repo_name}/bookmarks',
controller='bookmarks', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
controller='changelog', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)

View file

@ -1,85 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-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/
from pylons import tmpl_context as c
from rhodecode.controllers import utils
from rhodecode.lib import helpers as h
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
from rhodecode.lib.base import BaseRepoController, render
from rhodecode.lib.ext_json import json
from rhodecode.lib.utils import PartialRenderer
from rhodecode.lib.utils2 import datetime_to_time
class BaseReferencesController(BaseRepoController):
"""
Base for reference controllers for branches, tags and bookmarks.
Implement and set the following things:
- `partials_template` is the source for the partials to use.
- `template` is the template to render in the end.
- `_get_reference_items(repo)` should return a sequence of tuples which
map from `name` to `commit_id`.
"""
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def index(self):
_render = PartialRenderer(self.partials_template)
_data = []
pre_load = ["author", "date", "message"]
repo = c.rhodecode_repo
is_svn = h.is_svn(repo)
format_ref_id = utils.get_format_ref_id(repo)
for ref_name, commit_id in self._get_reference_items(repo):
commit = repo.get_commit(
commit_id=commit_id, pre_load=pre_load)
# TODO: johbo: Unify generation of reference links
use_commit_id = '/' in ref_name or is_svn
files_url = h.url(
'files_home',
repo_name=c.repo_name,
f_path=ref_name if is_svn else '',
revision=commit_id if use_commit_id else ref_name,
at=ref_name)
_data.append({
"name": _render('name', ref_name, files_url),
"name_raw": ref_name,
"date": _render('date', commit.date),
"date_raw": datetime_to_time(commit.date),
"author": _render('author', commit.author),
"commit": _render(
'commit', commit.message, commit.raw_id, commit.idx),
"commit_raw": commit.idx,
"compare": _render(
'compare', format_ref_id(ref_name, commit.raw_id)),
})
c.has_references = bool(_data)
c.data = json.dumps(_data)
return render(self.template)

View file

@ -1,45 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-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/
"""
branches controller for rhodecode
"""
import logging
from pylons import tmpl_context as c
from rhodecode.controllers.base_references import BaseReferencesController
log = logging.getLogger(__name__)
class BranchesController(BaseReferencesController):
partials_template = 'branches/branches_data.mako'
template = 'branches/branches.mako'
def __before__(self):
super(BranchesController, self).__before__()
c.closed_branches = c.rhodecode_repo.branches_closed
def _get_reference_items(self, repo):
return repo.branches_all.items()

View file

@ -1,38 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2010-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/
"""
Tags controller for rhodecode
"""
import logging
from rhodecode.controllers.base_references import BaseReferencesController
log = logging.getLogger(__name__)
class TagsController(BaseReferencesController):
partials_template = 'tags/tags_data.mako'
template = 'tags/tags.mako'
def _get_reference_items(self, repo):
return repo.tags.items()

View file

@ -96,6 +96,9 @@ function registerRCRoutes() {
pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
pyroutes.register('repo_list_data', '/_repos', []);
pyroutes.register('goto_switcher_data', '/_goto_data', []);
pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);

View file

@ -1,27 +1,27 @@
<%def name="refs_counters(branches, closed_branches, tags, bookmarks)">
<span class="branchtag tag">
<a href="${h.url('branches_home',repo_name=c.repo_name)}" class="childs">
<a href="${h.route_path('branches_home',repo_name=c.repo_name)}" class="childs">
<i class="icon-branch"></i>${ungettext(
'%(num)s Branch','%(num)s Branches', len(branches)) % {'num': len(branches)}}</a>
</span>
%if closed_branches:
<span class="branchtag tag">
<a href="${h.url('branches_home',repo_name=c.repo_name)}" class="childs">
<a href="${h.route_path('branches_home',repo_name=c.repo_name)}" class="childs">
<i class="icon-branch"></i>${ungettext(
'%(num)s Closed Branch', '%(num)s Closed Branches', len(closed_branches)) % {'num': len(closed_branches)}}</a>
</span>
%endif
<span class="tagtag tag">
<a href="${h.url('tags_home',repo_name=c.repo_name)}" class="childs">
<a href="${h.route_path('tags_home',repo_name=c.repo_name)}" class="childs">
<i class="icon-tag"></i>${ungettext(
'%(num)s Tag', '%(num)s Tags', len(tags)) % {'num': len(tags)}}</a>
</span>
%if bookmarks:
<span class="booktag tag">
<a href="${h.url('bookmarks_home',repo_name=c.repo_name)}" class="childs">
<a href="${h.route_path('bookmarks_home',repo_name=c.repo_name)}" class="childs">
<i class="icon-bookmark"></i>${ungettext(
'%(num)s Bookmark', '%(num)s Bookmarks', len(bookmarks)) % {'num': len(bookmarks)}}</a>
</span>