##// END OF EJS Templates
user-groups: fix potential problem with group sync of external plugins....
user-groups: fix potential problem with group sync of external plugins. - when using external plugin we used to check for a parameter that set the sync mode. The problem is we only checked if the flag was there. So toggling sync on and off set the value and then left the key still set but with None. This confused the sync and thought the group should be synced !

File last commit:

r2132:d9e584d8 default
r2143:4314e88b default
Show More
repo_changelog.py
342 lines | 13.0 KiB | text/x-python | PythonLexer
changelog: ported to pyramid views.
r1931 # -*- 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/
import logging
from pyramid.httpexceptions import HTTPNotFound, HTTPFound
from pyramid.view import view_config
from pyramid.renderers import render
from pyramid.response import Response
from rhodecode.apps._base import RepoAppView
import rhodecode.lib.helpers as h
from rhodecode.lib.auth import (
LoginRequired, HasRepoPermissionAnyDecorator)
from rhodecode.lib.ext_json import json
from rhodecode.lib.graphmod import _colored, _dagwalker
from rhodecode.lib.helpers import RepoPage
from rhodecode.lib.utils2 import safe_int, safe_str
from rhodecode.lib.vcs.exceptions import (
RepositoryError, CommitDoesNotExistError,
CommitError, NodeDoesNotExistError, EmptyRepositoryError)
log = logging.getLogger(__name__)
DEFAULT_CHANGELOG_SIZE = 20
class RepoChangelogView(RepoAppView):
def _get_commit_or_redirect(self, commit_id, redirect_after=True):
"""
This is a safe way to get commit. If an error occurs it redirects to
tip with proper message
:param commit_id: id of commit to fetch
:param redirect_after: toggle redirection
"""
_ = self.request.translate
try:
return self.rhodecode_vcs_repo.get_commit(commit_id)
except EmptyRepositoryError:
if not redirect_after:
return None
h.flash(h.literal(
_('There are no commits yet')), category='warning')
raise HTTPFound(
h.route_path('repo_summary', repo_name=self.db_repo_name))
except (CommitDoesNotExistError, LookupError):
msg = _('No such commit exists for this repository')
h.flash(msg, category='error')
raise HTTPNotFound()
except RepositoryError as e:
h.flash(safe_str(h.escape(e)), category='error')
raise HTTPNotFound()
def _graph(self, repo, commits, prev_data=None, next_data=None):
"""
Generates a DAG graph for repo
:param repo: repo instance
:param commits: list of commits
"""
if not commits:
changelog: fix consistency of returned data to 2 element tuple.
r2132 return json.dumps([]), json.dumps([])
changelog: ported to pyramid views.
r1931
def serialize(commit, parents=True):
data = dict(
raw_id=commit.raw_id,
idx=commit.idx,
branch=commit.branch,
)
if parents:
data['parents'] = [
serialize(x, parents=False) for x in commit.parents]
return data
prev_data = prev_data or []
next_data = next_data or []
current = [serialize(x) for x in commits]
commits = prev_data + current + next_data
dag = _dagwalker(repo, commits)
data = [[commit_id, vtx, edges, branch]
for commit_id, vtx, edges, branch in _colored(dag)]
return json.dumps(data), json.dumps(current)
def _check_if_valid_branch(self, branch_name, repo_name, f_path):
if branch_name not in self.rhodecode_vcs_repo.branches_all:
h.flash('Branch {} is not found.'.format(h.escape(branch_name)),
category='warning')
redirect_url = h.route_path(
'repo_changelog_file', repo_name=repo_name,
commit_id=branch_name, f_path=f_path or '')
raise HTTPFound(redirect_url)
def _load_changelog_data(
self, c, collection, page, chunk_size, branch_name=None,
changelog: fix url generation for file changelog and ensure...
r2124 dynamic=False, f_path=None, commit_id=None):
changelog: ported to pyramid views.
r1931
def url_generator(**kw):
query_params = {}
query_params.update(kw)
changelog: fix url generation for file changelog and ensure...
r2124 if f_path:
# changelog for file
return h.route_path(
'repo_changelog_file',
repo_name=c.rhodecode_db_repo.repo_name,
commit_id=commit_id, f_path=f_path,
_query=query_params)
else:
return h.route_path(
'repo_changelog',
repo_name=c.rhodecode_db_repo.repo_name, _query=query_params)
changelog: ported to pyramid views.
r1931
c.total_cs = len(collection)
c.showing_commits = min(chunk_size, c.total_cs)
c.pagination = RepoPage(collection, page=page, item_count=c.total_cs,
items_per_page=chunk_size, branch=branch_name,
url=url_generator)
c.next_page = c.pagination.next_page
c.prev_page = c.pagination.previous_page
if dynamic:
if self.request.GET.get('chunk') != 'next':
c.next_page = None
if self.request.GET.get('chunk') != 'prev':
c.prev_page = None
page_commit_ids = [x.raw_id for x in c.pagination]
c.comments = c.rhodecode_db_repo.get_comments(page_commit_ids)
c.statuses = c.rhodecode_db_repo.statuses(page_commit_ids)
def load_default_context(self):
c = self._get_local_tmpl_context(include_app_defaults=True)
c.rhodecode_repo = self.rhodecode_vcs_repo
self._register_global_c(c)
return c
changelog: fix and optimize loading of chunks for file history....
r2130 def _get_preload_attrs(self):
pre_load = ['author', 'branch', 'date', 'message', 'parents',
'obsolete', 'phase', 'hidden']
return pre_load
changelog: ported to pyramid views.
r1931 @LoginRequired()
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_changelog', request_method='GET',
renderer='rhodecode:templates/changelog/changelog.mako')
@view_config(
route_name='repo_changelog_file', request_method='GET',
renderer='rhodecode:templates/changelog/changelog.mako')
def repo_changelog(self):
c = self.load_default_context()
commit_id = self.request.matchdict.get('commit_id')
f_path = self._get_f_path(self.request.matchdict)
chunk_size = 20
c.branch_name = branch_name = self.request.GET.get('branch') or ''
c.book_name = book_name = self.request.GET.get('bookmark') or ''
changelog: fix and optimize loading of chunks for file history....
r2130 c.f_path = f_path
c.commit_id = commit_id
changelog: ported to pyramid views.
r1931 hist_limit = safe_int(self.request.GET.get('limit')) or None
p = safe_int(self.request.GET.get('page', 1), 1)
c.selected_name = branch_name or book_name
if not commit_id and branch_name:
self._check_if_valid_branch(branch_name, self.db_repo_name, f_path)
c.changelog_for_path = f_path
changelog: fix and optimize loading of chunks for file history....
r2130 pre_load = self._get_preload_attrs()
changelog: ported to pyramid views.
r1931
partial_xhr = self.request.environ.get('HTTP_X_PARTIAL_XHR')
try:
if f_path:
log.debug('generating changelog for path %s', f_path)
# get the history for the file !
base_commit = self.rhodecode_vcs_repo.get_commit(commit_id)
changelog: fix and optimize loading of chunks for file history....
r2130
changelog: ported to pyramid views.
r1931 try:
collection = base_commit.get_file_history(
f_path, limit=hist_limit, pre_load=pre_load)
if collection and partial_xhr:
# for ajax call we remove first one since we're looking
# at it right now in the context of a file commit
collection.pop(0)
except (NodeDoesNotExistError, CommitError):
# this node is not present at tip!
try:
commit = self._get_commit_or_redirect(commit_id)
collection = commit.get_file_history(f_path)
except RepositoryError as e:
h.flash(safe_str(e), category='warning')
redirect_url = h.route_path(
'repo_changelog', repo_name=self.db_repo_name)
raise HTTPFound(redirect_url)
collection = list(reversed(collection))
else:
collection = self.rhodecode_vcs_repo.get_commits(
branch_name=branch_name, pre_load=pre_load)
self._load_changelog_data(
changelog: fix url generation for file changelog and ensure...
r2124 c, collection, p, chunk_size, c.branch_name,
f_path=f_path, commit_id=commit_id)
changelog: ported to pyramid views.
r1931
except EmptyRepositoryError as e:
h.flash(safe_str(h.escape(e)), category='warning')
raise HTTPFound(
h.route_path('repo_summary', repo_name=self.db_repo_name))
changelog: fix url generation for file changelog and ensure...
r2124 except HTTPFound:
raise
changelog: ported to pyramid views.
r1931 except (RepositoryError, CommitDoesNotExistError, Exception) as e:
log.exception(safe_str(e))
h.flash(safe_str(h.escape(e)), category='error')
raise HTTPFound(
h.route_path('repo_changelog', repo_name=self.db_repo_name))
if partial_xhr or self.request.environ.get('HTTP_X_PJAX'):
changelog: fix and optimize loading of chunks for file history....
r2130 # case when loading dynamic file history in file view
changelog: ported to pyramid views.
r1931 # loading from ajax, we don't want the first result, it's popped
# in the code above
html = render(
'rhodecode:templates/changelog/changelog_file_history.mako',
self._get_template_context(c), self.request)
return Response(html)
changelog: only load graph data when showing changelog for both commit and commit loaded via ajax chunks.
r2131 commit_ids = []
changelog: ported to pyramid views.
r1931 if not f_path:
changelog: only load graph data when showing changelog for both commit and commit loaded via ajax chunks.
r2131 # only load graph data when not in file history mode
changelog: ported to pyramid views.
r1931 commit_ids = c.pagination
c.graph_data, c.graph_commits = self._graph(
self.rhodecode_vcs_repo, commit_ids)
return self._get_template_context(c)
@LoginRequired()
@HasRepoPermissionAnyDecorator(
'repository.read', 'repository.write', 'repository.admin')
@view_config(
route_name='repo_changelog_elements', request_method=('GET', 'POST'),
renderer='rhodecode:templates/changelog/changelog_elements.mako',
xhr=True)
changelog: fix and optimize loading of chunks for file history....
r2130 @view_config(
route_name='repo_changelog_elements_file', request_method=('GET', 'POST'),
renderer='rhodecode:templates/changelog/changelog_elements.mako',
xhr=True)
changelog: ported to pyramid views.
r1931 def repo_changelog_elements(self):
c = self.load_default_context()
changelog: fix and optimize loading of chunks for file history....
r2130 commit_id = self.request.matchdict.get('commit_id')
f_path = self._get_f_path(self.request.matchdict)
changelog: ported to pyramid views.
r1931 chunk_size = 20
changelog: fix and optimize loading of chunks for file history....
r2130 hist_limit = safe_int(self.request.GET.get('limit')) or None
changelog: ported to pyramid views.
r1931
def wrap_for_error(err):
html = '<tr>' \
'<td colspan="9" class="alert alert-error">ERROR: {}</td>' \
'</tr>'.format(err)
return Response(html)
c.branch_name = branch_name = self.request.GET.get('branch') or ''
c.book_name = book_name = self.request.GET.get('bookmark') or ''
changelog: fix and optimize loading of chunks for file history....
r2130 c.f_path = f_path
c.commit_id = commit_id
changelog: ported to pyramid views.
r1931
c.selected_name = branch_name or book_name
if branch_name and branch_name not in self.rhodecode_vcs_repo.branches_all:
return wrap_for_error(
safe_str('Branch: {} is not valid'.format(branch_name)))
changelog: fix and optimize loading of chunks for file history....
r2130 pre_load = self._get_preload_attrs()
if f_path:
base_commit = self.rhodecode_vcs_repo.get_commit(commit_id)
collection = base_commit.get_file_history(
f_path, limit=hist_limit, pre_load=pre_load)
collection = list(reversed(collection))
else:
collection = self.rhodecode_vcs_repo.get_commits(
branch_name=branch_name, pre_load=pre_load)
changelog: ported to pyramid views.
r1931
p = safe_int(self.request.GET.get('page', 1), 1)
try:
self._load_changelog_data(
changelog: fix and optimize loading of chunks for file history....
r2130 c, collection, p, chunk_size, dynamic=True,
f_path=f_path, commit_id=commit_id)
changelog: ported to pyramid views.
r1931 except EmptyRepositoryError as e:
return wrap_for_error(safe_str(e))
except (RepositoryError, CommitDoesNotExistError, Exception) as e:
log.exception('Failed to fetch commits')
return wrap_for_error(safe_str(e))
prev_data = None
next_data = None
changelog: fix and optimize loading of chunks for file history....
r2130 prev_graph = json.loads(self.request.POST.get('graph') or '{}')
changelog: ported to pyramid views.
r1931
if self.request.GET.get('chunk') == 'prev':
next_data = prev_graph
elif self.request.GET.get('chunk') == 'next':
prev_data = prev_graph
changelog: only load graph data when showing changelog for both commit and commit loaded via ajax chunks.
r2131 commit_ids = []
if not f_path:
# only load graph data when not in file history mode
commit_ids = c.pagination
changelog: ported to pyramid views.
r1931 c.graph_data, c.graph_commits = self._graph(
changelog: only load graph data when showing changelog for both commit and commit loaded via ajax chunks.
r2131 self.rhodecode_vcs_repo, commit_ids,
changelog: ported to pyramid views.
r1931 prev_data=prev_data, next_data=next_data)
return self._get_template_context(c)