Changeset - 60ae17de2a8d
[Not reviewed]
default
0 5 0
Mads Kiilerich - 12 years ago 2013-12-10 19:30:37
madski@unity3d.com
compare: add options for ignore whitespace and increase context
5 files changed with 29 insertions and 5 deletions:
0 comments (0 inline, 0 general)
kallithea/controllers/compare.py
Show inline comments
 
@@ -24,49 +24,50 @@ Original author and date, and relevant c
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH, and others.
 
:license: GPLv3, see LICENSE.md for more details.
 
"""
 

	
 

	
 
import logging
 
import traceback
 
import re
 

	
 
from webob.exc import HTTPNotFound, HTTPBadRequest
 
from pylons import request, response, session, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 

	
 
from kallithea.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError
 
from kallithea.lib.vcs.utils import safe_str
 
from kallithea.lib.vcs.utils.hgcompat import unionrepo
 
from kallithea.lib import helpers as h
 
from kallithea.lib.base import BaseRepoController, render
 
from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from kallithea.lib import diffs
 
from kallithea.model.db import Repository
 
from kallithea.lib.diffs import LimitedDiffContainer
 

	
 
from kallithea.controllers.changeset import anchor_url, _ignorews_url,\
 
    _context_url, get_line_ctx, get_ignore_ws
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class CompareController(BaseRepoController):
 

	
 
    def __before__(self):
 
        super(CompareController, self).__before__()
 

	
 
    def __get_rev_or_redirect(self, ref, repo, redirect_after=True,
 
                              partial=False):
 
        """
 
        Safe way to get changeset if error occur it redirects to changeset with
 
        proper message. If partial is set then don't do redirect raise Exception
 
        instead
 

	
 
        :param ref:
 
        :param repo:
 
        :param redirect_after:
 
        :param partial:
 
        """
 
        rev = ref[1] # default and used for git
 
        if repo.scm_instance.alias == 'hg':
 
            # lookup up the exact node id
 
@@ -204,48 +205,54 @@ class CompareController(BaseRepoControll
 
        other_repo = request.GET.get('other_repo', org_repo)
 
        # If merge is True:
 
        #   Show what org would get if merged with other:
 
        #   List changesets that are ancestors of other but not of org.
 
        #   New changesets in org is thus ignored.
 
        #   Diff will be from common ancestor, and merges of org to other will thus be ignored.
 
        # If merge is False:
 
        #   Make a raw diff from org to other, no matter if related or not.
 
        #   Changesets in one and not in the other will be ignored
 
        merge = bool(request.GET.get('merge'))
 
        # fulldiff disables cut_off_limit
 
        c.fulldiff = request.GET.get('fulldiff')
 
        # partial uses compare_cs.html template directly
 
        partial = request.environ.get('HTTP_X_PARTIAL_XHR')
 
        # as_form puts hidden input field with changeset revisions
 
        c.as_form = partial and request.GET.get('as_form')
 
        # swap url for compare_diff page - never partial and never as_form
 
        c.swap_url = h.url('compare_url',
 
            repo_name=other_repo,
 
            org_ref_type=other_ref_type, org_ref_name=other_ref_name,
 
            other_repo=org_repo,
 
            other_ref_type=org_ref_type, other_ref_name=org_ref_name,
 
            merge=merge or '')
 

	
 
        # set callbacks for generating markup for icons
 
        c.ignorews_url = _ignorews_url
 
        c.context_url = _context_url
 
        ignore_whitespace = request.GET.get('ignorews') == '1'
 
        line_context = request.GET.get('context', 3)
 

	
 
        org_repo = Repository.get_by_repo_name(org_repo)
 
        other_repo = Repository.get_by_repo_name(other_repo)
 

	
 
        if org_repo is None:
 
            msg = 'Could not find org repo %s' % org_repo
 
            log.error(msg)
 
            h.flash(msg, category='error')
 
            return redirect(url('compare_home', repo_name=c.repo_name))
 

	
 
        if other_repo is None:
 
            msg = 'Could not find other repo %s' % other_repo
 
            log.error(msg)
 
            h.flash(msg, category='error')
 
            return redirect(url('compare_home', repo_name=c.repo_name))
 

	
 
        if org_repo.scm_instance.alias != other_repo.scm_instance.alias:
 
            msg = 'compare of two different kind of remote repos not available'
 
            log.error(msg)
 
            h.flash(msg, category='error')
 
            return redirect(url('compare_home', repo_name=c.repo_name))
 

	
 
        c.org_rev = self.__get_rev_or_redirect(ref=org_ref, repo=org_repo, partial=partial)
 
        c.other_rev = self.__get_rev_or_redirect(ref=other_ref, repo=other_repo, partial=partial)
 

	
 
@@ -264,49 +271,51 @@ class CompareController(BaseRepoControll
 
            [x.raw_id for x in c.cs_ranges])
 

	
 
        if partial:
 
            return render('compare/compare_cs.html')
 
        if merge and c.ancestor:
 
            # case we want a simple diff without incoming changesets,
 
            # previewing what will be merged.
 
            # Make the diff on the other repo (which is known to have other_rev)
 
            log.debug('Using ancestor %s as rev1 instead of %s'
 
                      % (c.ancestor, c.org_rev))
 
            rev1 = c.ancestor
 
            org_repo = other_repo
 
        else: # comparing tips, not necessarily linearly related
 
            if merge:
 
                log.error('Unable to find ancestor revision')
 
            if org_repo != other_repo:
 
                log.error('cannot compare across repos %s and %s', org_repo, other_repo)
 
                raise HTTPNotFound
 
            rev1 = c.org_rev
 

	
 
        diff_limit = self.cut_off_limit if not c.fulldiff else None
 

	
 
        log.debug('running diff between %s and %s in %s'
 
                  % (rev1, c.other_rev, org_repo.scm_instance.path))
 
        txtdiff = org_repo.scm_instance.get_diff(rev1=rev1, rev2=c.other_rev)
 
        txtdiff = org_repo.scm_instance.get_diff(rev1=rev1, rev2=c.other_rev,
 
                                      ignore_whitespace=ignore_whitespace,
 
                                      context=line_context)
 

	
 
        diff_processor = diffs.DiffProcessor(txtdiff or '', format='gitdiff',
 
                                             diff_limit=diff_limit)
 
        _parsed = diff_processor.prepare()
 

	
 
        c.limited_diff = False
 
        if isinstance(_parsed, LimitedDiffContainer):
 
            c.limited_diff = True
 

	
 
        c.files = []
 
        c.changes = {}
 
        c.lines_added = 0
 
        c.lines_deleted = 0
 
        for f in _parsed:
 
            st = f['stats']
 
            if not st['binary']:
 
                c.lines_added += st['added']
 
                c.lines_deleted += st['deleted']
 
            fid = h.FID('', f['filename'])
 
            c.files.append([fid, f['operation'], f['filename'], f['stats']])
 
            htmldiff = diff_processor.as_html(enable_comments=False, parsed_lines=[f])
 
            c.changes[fid] = [f['operation'], f['filename'], htmldiff]
 

	
 
        return render('compare/compare_diff.html')
kallithea/controllers/pullrequests.py
Show inline comments
 
@@ -36,48 +36,50 @@ from itertools import groupby
 
from pylons import request, tmpl_context as c, url
 
from pylons.controllers.util import redirect
 
from pylons.i18n.translation import _
 

	
 
from kallithea.lib.compat import json
 
from kallithea.lib.base import BaseRepoController, render
 
from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\
 
    NotAnonymous
 
from kallithea.lib.helpers import Page
 
from kallithea.lib import helpers as h
 
from kallithea.lib import diffs
 
from kallithea.lib.utils import action_logger, jsonify
 
from kallithea.lib.vcs.utils import safe_str
 
from kallithea.lib.vcs.exceptions import EmptyRepositoryError
 
from kallithea.lib.diffs import LimitedDiffContainer
 
from kallithea.model.db import  PullRequest, ChangesetStatus, ChangesetComment,\
 
    PullRequestReviewers
 
from kallithea.model.pull_request import PullRequestModel
 
from kallithea.model.meta import Session
 
from kallithea.model.repo import RepoModel
 
from kallithea.model.comment import ChangesetCommentsModel
 
from kallithea.model.changeset_status import ChangesetStatusModel
 
from kallithea.model.forms import PullRequestForm
 
from kallithea.lib.utils2 import safe_int
 
from kallithea.controllers.changeset import anchor_url, _ignorews_url,\
 
    _context_url, get_line_ctx, get_ignore_ws
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class PullrequestsController(BaseRepoController):
 

	
 
    def __before__(self):
 
        super(PullrequestsController, self).__before__()
 
        repo_model = RepoModel()
 
        c.users_array = repo_model.get_users_js()
 
        c.user_groups_array = repo_model.get_user_groups_js()
 

	
 
    def _get_repo_refs(self, repo, rev=None, branch=None, branch_rev=None):
 
        """return a structure with repo's interesting changesets, suitable for
 
        the selectors in pullrequest.html
 

	
 
        rev: a revision that must be in the list somehow and selected by default
 
        branch: a branch that must be in the list and selected by default - even if closed
 
        branch_rev: a revision of which peers should be preferred and available."""
 
        # list named branches that has been merged to this named branch - it should probably merge back
 
        peers = []
 

	
 
        if rev:
 
            rev = safe_str(rev)
 
@@ -173,55 +175,61 @@ class PullrequestsController(BaseRepoCon
 
                                                   pull_request.reviewers]
 
        return self.authuser.admin or owner or reviewer
 

	
 
    def _load_compare_data(self, pull_request, enable_comments=True):
 
        """
 
        Load context data needed for generating compare diff
 

	
 
        :param pull_request:
 
        """
 
        c.org_repo = pull_request.org_repo
 
        (c.org_ref_type,
 
         c.org_ref_name,
 
         c.org_rev) = pull_request.org_ref.split(':')
 

	
 
        c.other_repo = c.org_repo
 
        (c.other_ref_type,
 
         c.other_ref_name,
 
         c.other_rev) = pull_request.other_ref.split(':')
 

	
 
        c.cs_ranges = [c.org_repo.get_changeset(x) for x in pull_request.revisions]
 
        c.cs_ranges_org = None # not stored and not important and moving target - could be calculated ...
 

	
 
        c.statuses = c.org_repo.statuses([x.raw_id for x in c.cs_ranges])
 

	
 
        ignore_whitespace = request.GET.get('ignorews') == '1'
 
        line_context = request.GET.get('context', 3)
 
        c.ignorews_url = _ignorews_url
 
        c.context_url = _context_url
 
        c.fulldiff = request.GET.get('fulldiff')
 
        diff_limit = self.cut_off_limit if not c.fulldiff else None
 

	
 
        # we swap org/other ref since we run a simple diff on one repo
 
        log.debug('running diff between %s and %s in %s'
 
                  % (c.other_rev, c.org_rev, c.org_repo.scm_instance.path))
 
        txtdiff = c.org_repo.scm_instance.get_diff(rev1=safe_str(c.other_rev), rev2=safe_str(c.org_rev))
 
        txtdiff = c.org_repo.scm_instance.get_diff(rev1=safe_str(c.other_rev), rev2=safe_str(c.org_rev),
 
                                      ignore_whitespace=ignore_whitespace,
 
                                      context=line_context)
 

	
 
        diff_processor = diffs.DiffProcessor(txtdiff or '', format='gitdiff',
 
                                             diff_limit=diff_limit)
 
        _parsed = diff_processor.prepare()
 

	
 
        c.limited_diff = False
 
        if isinstance(_parsed, LimitedDiffContainer):
 
            c.limited_diff = True
 

	
 
        c.files = []
 
        c.changes = {}
 
        c.lines_added = 0
 
        c.lines_deleted = 0
 

	
 
        for f in _parsed:
 
            st = f['stats']
 
            c.lines_added += st['added']
 
            c.lines_deleted += st['deleted']
 
            fid = h.FID('', f['filename'])
 
            c.files.append([fid, f['operation'], f['filename'], f['stats']])
 
            htmldiff = diff_processor.as_html(enable_comments=enable_comments,
 
                                              parsed_lines=[f])
 
            c.changes[fid] = [f['operation'], f['filename'], htmldiff]
 

	
kallithea/templates/changeset/diff_block.html
Show inline comments
 
@@ -59,34 +59,36 @@
 
          <div class="changeset_header">
 
              <div class="changeset_file">
 
                  ${h.safe_unicode(filenode_path)} |
 
                  ## TODO: link to ancestor and head of other instead of exactly other
 
                  %if op == 'A':
 
                    ${_('Added')}
 
                    <a class="spantag" href="${h.url('files_home', repo_name=c.org_repo.repo_name, f_path=filenode_path, revision=c.org_rev)}">${h.short_id(c.org_ref_name) if c.org_ref_type=='rev' else c.org_ref_name}</a>
 
                  %elif op == 'M':
 
                    <a class="spantag" href="${h.url('files_home', repo_name=c.org_repo.repo_name, f_path=filenode_path, revision=c.org_rev)}">${h.short_id(c.org_ref_name) if c.org_ref_type=='rev' else c.org_ref_name}</a>
 
                    <i class="icon-arrow-right"></i>
 
                    <a class="spantag" href="${h.url('files_home', repo_name=c.other_repo.repo_name, f_path=filenode_path, revision=c.other_rev)}">${h.short_id(c.other_ref_name) if c.other_ref_type=='rev' else c.other_ref_name}</a>
 
                  %elif op == 'D':
 
                    ${_('Deleted')}
 
                    <a class="spantag" href="${h.url('files_home', repo_name=c.other_repo.repo_name, f_path=filenode_path, revision=c.other_rev)}">${h.short_id(c.other_ref_name) if c.other_ref_type=='rev' else c.other_ref_name}</a>
 
                  %else:
 
                    ${op}???
 
                  %endif
 
              </div>
 
               <div class="diff-actions">
 
                %if c.other_repo.repo_name == c.repo_name:
 
                  <a href="${h.url('files_diff_2way_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode_path),diff2=c.other_rev,diff1=c.org_rev,diff='diff',fulldiff=1)}" class="tooltip" title="${h.tooltip(_('Show full side-by-side diff for this file'))}">
 
                      <img class="icon" src="${h.url('/images/icons/application_double.png')}"/>
 
                  </a>
 
                %endif
 
                ${c.ignorews_url(request.GET)}
 
                ${c.context_url(request.GET)}
 
                </div>
 
          </div>
 
      </div>
 
        <div class="code-body">
 
            <div class="full_f_path" path="${h.safe_unicode(filenode_path)}"></div>
 
            ${diff|n}
 
        </div>
 
    </div>
 
  %endfor
 
</%def>
kallithea/templates/compare/compare_diff.html
Show inline comments
 
@@ -38,48 +38,51 @@ ${self.repo_context_bar('changelog')}
 
                    <div id="compare_revs" class="btn btn-small"><i class="icon-loop"></i> ${_('Compare Revisions')}</div>
 
                </div>
 
            </div>
 
        </div>
 

	
 
    %if c.compare_home:
 
        <div id="changeset_compare_view_content">
 
         <div style="color:#999;font-size: 18px">${_('Compare revisions, branches, bookmarks or tags.')}</div>
 
        </div>
 
    %else:
 
        <div id="changeset_compare_view_content">
 
                ##CS
 
                <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${ungettext('Showing %s commit','Showing %s commits', len(c.cs_ranges)) % len(c.cs_ranges)}</div>
 
                <%include file="compare_cs.html" />
 

	
 
                ## FILES
 
                <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
 

	
 
                % if c.limited_diff:
 
                    ${ungettext('%s file changed', '%s files changed', len(c.files)) % len(c.files)}
 
                % else:
 
                    ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.files)) % (len(c.files),c.lines_added,c.lines_deleted)}:
 
                %endif
 

	
 
                ${c.ignorews_url(request.GET)}
 
                ${c.context_url(request.GET)}
 

	
 
                </div>
 
                <div class="cs_files">
 
                  %if not c.files:
 
                     <span class="empty_data">${_('No files')}</span>
 
                  %endif
 
                  %for fid, change, f, stat in c.files:
 
                      <div class="cs_${change}">
 
                        <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid, **request.GET.mixed()))}</div>
 
                        <div class="changes">${h.fancy_file_stats(stat)}</div>
 
                      </div>
 
                  %endfor
 
                </div>
 
                % if c.limited_diff:
 
                  <h5>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff')}</a></h5>
 
                % endif
 
         </div>
 

	
 
        ## diff block
 
        <%namespace name="diff_block" file="/changeset/diff_block.html"/>
 
        %for fid, change, f, stat in c.files:
 
          ${diff_block.diff_block_simple([c.changes[fid]])}
 
        %endfor
 
        % if c.limited_diff:
 
          <h4>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff')}</a></h4>
kallithea/templates/pullrequests/pullrequest_show.html
Show inline comments
 
@@ -134,50 +134,52 @@ ${self.repo_context_bar('showpullrequest
 
              </li>
 
            %endfor
 
            </ul>
 
          </div>
 
          %if not c.pull_request.is_closed():
 
          <div class='ac'>
 
            %if h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or c.pull_request.author.user_id == c.authuser.user_id:
 
            <div class="reviewer_ac">
 
               ${h.text('user', class_='yui-ac-input')}
 
               <span class="help-block">${_('Add or remove reviewer to this pull request.')}</span>
 
               <div id="reviewers_container"></div>
 
            </div>
 
            <div style="padding:0px 10px">
 
             <span id="update_pull_request" class="btn btn-mini">${_('Save Changes')}</span>
 
            </div>
 
            %endif
 
          </div>
 
          %endif
 
        </div>
 
       </div>
 

	
 
    <div style="overflow: auto; clear: both">
 
      ##DIFF
 
      <div class="table" style="float:left;clear:none">
 
          <div id="body" class="diffblock">
 
              <div style="white-space:pre-wrap;padding:5px">${_('Compare view')}</div>
 
          <div class="diffblock">
 
              <div style="padding:5px">
 
                ${_('Compare view')}
 
              </div>
 
          </div>
 
          <div id="changeset_compare_view_content">
 
              ##CS
 
              <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${ungettext('Showing %s commit','Showing %s commits', len(c.cs_ranges)) % len(c.cs_ranges)}</div>
 
              <%include file="/compare/compare_cs.html" />
 

	
 
              ## FILES
 
              <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
 

	
 
              % if c.limited_diff:
 
                  ${ungettext('%s file changed', '%s files changed', len(c.files)) % len(c.files)}
 
              % else:
 
                  ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.files)) % (len(c.files),c.lines_added,c.lines_deleted)}:
 
              %endif
 

	
 
              </div>
 
              <div class="cs_files">
 
                %if not c.files:
 
                   <span class="empty_data">${_('No files')}</span>
 
                %endif
 
                %for fid, change, f, stat in c.files:
 
                    <div class="cs_${change}">
 
                      <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
 
                      <div class="changes">${h.fancy_file_stats(stat)}</div>
0 comments (0 inline, 0 general)