##// END OF EJS Templates
todos: all todos needs to be resolved for merge to happen....
todos: all todos needs to be resolved for merge to happen. This will prevent the outdated todos beeing automatically marked as solved becuase of bigger diff changes. It's better to mark commits quickly as resolved instead of potentially have unresolved todos hidden because of invlidation logic.

File last commit:

r1282:90601d74 default
r1342:44fc3039 default
Show More
compare.py
282 lines | 11.2 KiB | text/x-python | PythonLexer
project: added all source files and assets
r1 # -*- coding: utf-8 -*-
license: updated copyright year to 2017
r1271 # Copyright (C) 2012-2017 RhodeCode GmbH
project: added all source files and assets
r1 #
# 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/
"""
Compare controller for showing differences between two commits/refs/tags etc.
"""
import logging
from webob.exc import HTTPBadRequest
from pylons import request, tmpl_context as c, url
from pylons.controllers.util import redirect
from pylons.i18n.translation import _
from rhodecode.controllers.utils import parse_path_ref, get_commit_from_ref_name
from rhodecode.lib import helpers as h
dan
diffs: replace compare controller with new html based diffs:...
r1030 from rhodecode.lib import diffs, codeblocks
project: added all source files and assets
r1 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
from rhodecode.lib.base import BaseRepoController, render
from rhodecode.lib.utils import safe_str
from rhodecode.lib.utils2 import safe_unicode, str2bool
from rhodecode.lib.vcs.exceptions import (
dan
diffs: replace compare controller with new html based diffs:...
r1030 EmptyRepositoryError, RepositoryError, RepositoryRequirementError,
NodeDoesNotExistError)
project: added all source files and assets
r1 from rhodecode.model.db import Repository, ChangesetStatus
log = logging.getLogger(__name__)
class CompareController(BaseRepoController):
def __before__(self):
super(CompareController, self).__before__()
def _get_commit_or_redirect(
self, ref, ref_type, repo, redirect_after=True, partial=False):
"""
This is a safe way to get a commit. If an error occurs it
redirects to a commit with a proper message. If partial is set
then it does not do redirect raise and throws an exception instead.
"""
try:
return get_commit_from_ref_name(repo, safe_str(ref), ref_type)
except EmptyRepositoryError:
if not redirect_after:
return repo.scm_instance().EMPTY_COMMIT
h.flash(h.literal(_('There are no commits yet')),
category='warning')
redirect(url('summary_home', repo_name=repo.repo_name))
except RepositoryError as e:
msg = safe_str(e)
log.exception(msg)
h.flash(msg, category='warning')
if not partial:
redirect(h.url('summary_home', repo_name=repo.repo_name))
raise HTTPBadRequest()
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def index(self, repo_name):
c.compare_home = True
c.commit_ranges = []
pull-requests: updated versioning support....
r1268 c.collapse_all_commits = False
dan
diffs: replace compare controller with new html based diffs:...
r1030 c.diffset = None
project: added all source files and assets
r1 c.limited_diff = False
source_repo = c.rhodecode_db_repo.repo_name
target_repo = request.GET.get('target_repo', source_repo)
c.source_repo = Repository.get_by_repo_name(source_repo)
c.target_repo = Repository.get_by_repo_name(target_repo)
c.source_ref = c.target_ref = _('Select commit')
c.source_ref_type = ""
c.target_ref_type = ""
c.commit_statuses = ChangesetStatus.STATUSES
c.preview_mode = False
diffs: compare overhaul....
r1259 c.file_path = None
templating: use .mako as extensions for template files.
r1282 return render('compare/compare_diff.mako')
project: added all source files and assets
r1
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def compare(self, repo_name, source_ref_type, source_ref,
target_ref_type, target_ref):
# source_ref will be evaluated in source_repo
source_repo_name = c.rhodecode_db_repo.repo_name
source_path, source_id = parse_path_ref(source_ref)
# target_ref will be evaluated in target_repo
target_repo_name = request.GET.get('target_repo', source_repo_name)
diffs: compare overhaul....
r1259 target_path, target_id = parse_path_ref(
target_ref, default_path=request.GET.get('f_path', ''))
project: added all source files and assets
r1
diffs: compare overhaul....
r1259 c.file_path = target_path
project: added all source files and assets
r1 c.commit_statuses = ChangesetStatus.STATUSES
# if merge is True
# Show what changes since the shared ancestor commit of target/source
# the source would get if it was merged with target. Only commits
# which are in target but not in source will be shown.
merge = str2bool(request.GET.get('merge'))
# if merge is False
# Show a raw diff of source/target refs even if no ancestor exists
# c.fulldiff disables cut_off_limit
c.fulldiff = str2bool(request.GET.get('fulldiff'))
# if partial, returns just compare_commits.html (commits log)
partial = request.is_xhr
# swap url for compare_diff page
c.swap_url = h.url(
'compare_url',
repo_name=target_repo_name,
source_ref_type=target_ref_type,
source_ref=target_ref,
target_repo=source_repo_name,
target_ref_type=source_ref_type,
target_ref=source_ref,
diffs: compare overhaul....
r1259 merge=merge and '1' or '',
f_path=target_path)
project: added all source files and assets
r1
source_repo = Repository.get_by_repo_name(source_repo_name)
target_repo = Repository.get_by_repo_name(target_repo_name)
if source_repo is None:
msg = _('Could not find the original repo: %(repo)s') % {
'repo': source_repo}
log.error(msg)
h.flash(msg, category='error')
return redirect(url('compare_home', repo_name=c.repo_name))
if target_repo is None:
msg = _('Could not find the other repo: %(repo)s') % {
'repo': target_repo_name}
log.error(msg)
h.flash(msg, category='error')
return redirect(url('compare_home', repo_name=c.repo_name))
diffs: compare overhaul....
r1259 source_scm = source_repo.scm_instance()
target_scm = target_repo.scm_instance()
source_alias = source_scm.alias
target_alias = target_scm.alias
project: added all source files and assets
r1 if source_alias != target_alias:
msg = _('The comparison of two different kinds of remote repos '
'is not available')
log.error(msg)
h.flash(msg, category='error')
return redirect(url('compare_home', repo_name=c.repo_name))
source_commit = self._get_commit_or_redirect(
ref=source_id, ref_type=source_ref_type, repo=source_repo,
partial=partial)
target_commit = self._get_commit_or_redirect(
ref=target_id, ref_type=target_ref_type, repo=target_repo,
partial=partial)
c.compare_home = False
c.source_repo = source_repo
c.target_repo = target_repo
c.source_ref = source_ref
c.target_ref = target_ref
c.source_ref_type = source_ref_type
c.target_ref_type = target_ref_type
pre_load = ["author", "branch", "date", "message"]
c.ancestor = None
compare: using f_path shouldn't generate full range of commits....
r1262
if c.file_path:
if source_commit == target_commit:
c.commit_ranges = []
else:
c.commit_ranges = [target_commit]
else:
try:
c.commit_ranges = source_scm.compare(
source_commit.raw_id, target_commit.raw_id,
target_scm, merge, pre_load=pre_load)
if merge:
c.ancestor = source_scm.get_common_ancestor(
source_commit.raw_id, target_commit.raw_id, target_scm)
except RepositoryRequirementError:
msg = _('Could not compare repos with different '
'large file settings')
log.error(msg)
if partial:
return msg
h.flash(msg, category='error')
return redirect(url('compare_home', repo_name=c.repo_name))
project: added all source files and assets
r1
c.statuses = c.rhodecode_db_repo.statuses(
[x.raw_id for x in c.commit_ranges])
pull-requests: updated versioning support....
r1268 # auto collapse if we have more than limit
collapse_limit = diffs.DiffProcessor._collapse_commits_over
c.collapse_all_commits = len(c.commit_ranges) > collapse_limit
diffs: compare overhaul....
r1259 if partial: # for PR ajax commits loader
dan
pullrequest: disable pr on commits that dont share ancestor
r64 if not c.ancestor:
diffs: compare overhaul....
r1259 return '' # cannot merge if there is no ancestor
templating: use .mako as extensions for template files.
r1282 return render('compare/compare_commits.mako')
project: added all source files and assets
r1
if c.ancestor:
# case we want a simple diff without incoming commits,
# previewing what will be merged.
# Make the diff on target repo (which is known to have target_ref)
log.debug('Using ancestor %s as source_ref instead of %s'
% (c.ancestor, source_ref))
source_repo = target_repo
source_commit = target_repo.get_commit(commit_id=c.ancestor)
# diff_limit will cut off the whole diff if the limit is applied
# otherwise it will just hide the big files from the front-end
diff_limit = self.cut_off_limit_diff
file_limit = self.cut_off_limit_file
log.debug('calculating diff between '
'source_ref:%s and target_ref:%s for repo `%s`',
source_commit, target_commit,
safe_unicode(source_repo.scm_instance().path))
if source_commit.repository != target_commit.repository:
msg = _(
"Repositories unrelated. "
"Cannot compare commit %(commit1)s from repository %(repo1)s "
"with commit %(commit2)s from repository %(repo2)s.") % {
'commit1': h.show_id(source_commit),
'repo1': source_repo.repo_name,
'commit2': h.show_id(target_commit),
'repo2': target_repo.repo_name,
}
h.flash(msg, category='error')
raise HTTPBadRequest()
txtdiff = source_repo.scm_instance().get_diff(
commit1=source_commit, commit2=target_commit,
diffs: compare overhaul....
r1259 path=target_path, path1=source_path)
project: added all source files and assets
r1 diff_processor = diffs.DiffProcessor(
dan
diffs: replace compare controller with new html based diffs:...
r1030 txtdiff, format='newdiff', diff_limit=diff_limit,
project: added all source files and assets
r1 file_limit=file_limit, show_full_diff=c.fulldiff)
_parsed = diff_processor.prepare()
dan
diffs: replace compare controller with new html based diffs:...
r1030 def _node_getter(commit):
""" Returns a function that returns a node for a commit or None """
def get_node(fname):
try:
return commit.get_node(fname)
except NodeDoesNotExistError:
return None
return get_node
project: added all source files and assets
r1
dan
diffs: replace compare controller with new html based diffs:...
r1030 c.diffset = codeblocks.DiffSet(
dan
diffs: add repo_name as parameter of diffset - fixes bug...
r1142 repo_name=source_repo.repo_name,
dan
diffs: replace compare controller with new html based diffs:...
r1030 source_node_getter=_node_getter(source_commit),
target_node_getter=_node_getter(target_commit),
).render_patchset(_parsed, source_ref, target_ref)
project: added all source files and assets
r1
c.preview_mode = merge
diffs: compare overhaul....
r1259 c.source_commit = source_commit
c.target_commit = target_commit
project: added all source files and assets
r1
templating: use .mako as extensions for template files.
r1282 return render('compare/compare_diff.mako')