@@ -25,12 +25,18 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
import traceback
from collections import defaultdict
from webob.exc import HTTPForbidden
from pylons import tmpl_context as c, url, request, response
from pylons.i18n.translation import _
from pylons.controllers.util import redirect
from pylons.decorators import jsonify
from vcs.exceptions import RepositoryError, ChangesetError, \
ChangesetDoesNotExistError
from vcs.nodes import FileNode
import rhodecode.lib.helpers as h
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
from rhodecode.lib.base import BaseRepoController, render
@@ -39,16 +45,109 @@ from rhodecode.lib.compat import Ordered
from rhodecode.lib import diffs
from rhodecode.model.db import ChangesetComment
from rhodecode.model.comment import ChangesetCommentsModel
from rhodecode.model.meta import Session
log = logging.getLogger(__name__)
def anchor_url(revision,path):
fid = h.FID(revision, path)
return h.url.current(anchor=fid,**request.GET)
def get_ignore_ws(fid, GET):
ig_ws_global = request.GET.get('ignorews')
ig_ws = filter(lambda k:k.startswith('WS'),GET.getall(fid))
if ig_ws:
try:
return int(ig_ws[0].split(':')[-1])
except:
pass
return ig_ws_global
def _ignorews_url(fileid=None):
params = defaultdict(list)
lbl = _('show white space')
ig_ws = get_ignore_ws(fileid, request.GET)
ln_ctx = get_line_ctx(fileid, request.GET)
# global option
if fileid is None:
if ig_ws is None:
params['ignorews'] += [1]
lbl = _('ignore white space')
ctx_key = 'context'
ctx_val = ln_ctx
# per file options
else:
params[fileid] += ['WS:1']
ctx_key = fileid
ctx_val = 'C:%s' % ln_ctx
# if we have passed in ln_ctx pass it along to our params
if ln_ctx:
params[ctx_key] += [ctx_val]
params['anchor'] = fileid
return h.link_to(lbl, h.url.current(**params))
def get_line_ctx(fid, GET):
ln_ctx_global = request.GET.get('context')
ln_ctx = filter(lambda k:k.startswith('C'),GET.getall(fid))
retval = ln_ctx[0].split(':')[-1]
retval = ln_ctx_global
return int(retval)
return
def _context_url(fileid=None):
"""
Generates url for context lines
:param fileid:
ln_ctx = (get_line_ctx(fileid, request.GET) or 3) * 2
if ln_ctx > 0:
params['context'] += [ln_ctx]
ig_ws_key = 'ignorews'
ig_ws_val = 1
# per file option
params[fileid] += ['C:%s' % ln_ctx]
ig_ws_key = fileid
ig_ws_val = 'WS:%s' % 1
params[ig_ws_key] += [ig_ws_val]
lbl = _('%s line context') % ln_ctx
def wrap_to_table(str_):
return '''<table class="code-difftable">
<tr class="line">
<td class="lineno new"></td>
<td class="code"><pre>%s</pre></td>
</tr>
</table>''' % str_
class ChangesetController(BaseRepoController):
@LoginRequired()
@@ -59,16 +158,10 @@ class ChangesetController(BaseRepoContro
c.affected_files_cut_off = 60
def index(self, revision):
ignore_whitespace = request.GET.get('ignorews') == '1'
line_context = request.GET.get('context', 3)
def wrap_to_table(str):
</table>''' % str
c.anchor_url = anchor_url
c.ignorews_url = _ignorews_url
c.context_url = _context_url
#get ranges of revisions if preset
rev_range = revision.split('...')[:2]
@@ -130,10 +223,13 @@ class ChangesetController(BaseRepoContro
# added nodes and their size defines how many changes were
# made
c.sum_added += node.size
fid = h.FID(revision, node.path)
line_context_lcl = get_line_ctx(fid, request.GET)
ignore_whitespace_lcl = get_ignore_ws(fid, request.GET)
if c.sum_added < self.cut_off_limit:
f_gitdiff = diffs.get_gitdiff(filenode_old, node,
ignore_whitespace=ignore_whitespace,
context=line_context)
ignore_whitespace=ignore_whitespace_lcl,
context=line_context_lcl)
d = diffs.DiffProcessor(f_gitdiff, format='gitdiff')
st = d.stat()
@@ -171,9 +267,12 @@ class ChangesetController(BaseRepoContro
if c.sum_removed < self.cut_off_limit:
ignore_whitespace_lcl = get_ignore_ws(fid, request.GET,)
d = diffs.DiffProcessor(f_gitdiff,
format='gitdiff')
@@ -52,6 +52,17 @@ def _reset(name, value=None, id=NotGiven
reset = _reset
safeid = _make_safe_id_component
def FID(raw_id,path):
Creates a uniqe ID for filenode based on it's path and revision
:param raw_id:
:param path:
return 'C-%s-%s' % (short_id(raw_id), safeid(safe_unicode(path)))
def get_token():
"""Return the current authentication token, creating one if one doesn't
already exist.
@@ -1890,7 +1890,9 @@ h3.files_location {
color: #556CB5;
white-space: pre-wrap;
}
#changeset_content .container .left .message a:hover {
text-decoration: none;
.cs_files .cur_cs {
margin: 10px 2px;
font-weight: bold;
@@ -2254,7 +2256,7 @@ table.code-browser .browser-file {
float: left;
.diffblock .changeset_header .diff-menu{
.diffblock .diff-menu{
position: absolute;
background: none repeat scroll 0 0 #FFFFFF;
border-color: #003367 #666666 #666666;
@@ -2267,14 +2269,14 @@ table.code-browser .browser-file {
.diffblock .changeset_header .diff-menu ul li {
.diffblock .diff-menu ul li {
padding: 0px 0px 0px 0px !important;
.diffblock .changeset_header .diff-menu ul li a{
.diffblock .diff-menu ul li a{
display: block;
padding: 3px 8px 3px 8px !important;
.diffblock .changeset_header .diff-menu ul li a:hover{
.diffblock .diff-menu ul li a:hover{
background-color: #EEEEEE;
@@ -3689,6 +3691,11 @@ div.diffblock .code-header{
border-bottom: 1px solid #CCCCCC;
background: #EEEEEE;
padding:10px 0 10px 0;
height: 14px;
div.diffblock .code-header .date{
float:left;
text-transform: uppercase;
div.diffblock .code-header div{
margin-left:4px;
@@ -18,12 +18,6 @@
${self.menu('changelog')}
</%def>
<%def name="fid(raw_id,path)" filter="strip">
<%
return 'C-%s-%s' % (h.short_id(raw_id),h.safeid(h.safe_unicode(path)))
%>
<%def name="main()">
<div class="box">
<!-- box / title -->
@@ -33,19 +27,24 @@
<div class="table">
<div class="diffblock">
<div class="code-header">
<div>
<span>${h.link_to(_('raw diff'),
h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</span>
» <span>${h.link_to(_('download diff'),
h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</span>
<div class="comments-number" style="float:right;padding-right:5px">${len(c.comments)} comment(s) (${c.inline_cnt} ${_('inline')})</div>
</div>
<div class="date">${_('commit')} ${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} ${c.changeset.date}</div>
<div class="diff-menu-wrapper">
<img class="diff-menu-activate" style="cursor: pointer" alt="diff-menu" src="${h.url('/images/icons/script_gear.png')}" />
<div class="diff-menu" style="display:none">
<ul>
<li>${h.link_to(_('raw diff'),h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</li>
<li>${h.link_to(_('download diff'),h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</li>
<li>${c.ignorews_url()}</li>
<li>${c.context_url()}</li>
</ul>
<div id="changeset_content">
<div class="container">
<div class="left">
<div class="date">${_('commit')} ${c.changeset.revision}: ${h.short_id(c.changeset.raw_id)}@${c.changeset.date}</div>
<div class="author">
<div class="gravatar">
<img alt="gravatar" src="${h.gravatar_url(h.email(c.changeset.author),20)}"/>
@@ -100,9 +99,9 @@
<div class="cs_${change}">
<div class="node">
%if change != 'removed':
${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=self.fid(filenode.changeset.raw_id,filenode.path)))}
${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path))}
%else:
${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=self.fid('',filenode.path)))}
${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID('',filenode.path)))}
%endif
<div class="changes">${h.fancy_file_stats(stat)}</div>
@@ -118,8 +117,8 @@
%for change,filenode,diff,cs1,cs2,stat in c.changes:
%if change !='removed':
<div style="clear:both;height:10px"></div>
<div class="diffblock margined comm" id="${self.fid(filenode.changeset.raw_id,filenode.path)}">
<div id="${h.FID(filenode.changeset.raw_id,filenode.path)}" style="clear:both;height:90px;margin-top:-60px"></div>
<div class="diffblock margined comm">
<div class="changeset_header">
<div class="changeset_file">
@@ -133,13 +132,15 @@
<li>${h.link_to(_('diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='diff'))}</li>
<li>${h.link_to(_('raw diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='raw'))}</li>
<li>${h.link_to(_('download diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='download'))}</li>
<li>${c.ignorews_url(h.FID(filenode.changeset.raw_id,filenode.path))}</li>
<li>${c.context_url(h.FID(filenode.changeset.raw_id,filenode.path))}</li>
<span style="float:right;margin-top:-3px">
<label>
${_('show inline comments')}
${h.checkbox('',checked="checked",class_="show-inline-comments",id_for=self.fid(filenode.changeset.raw_id,filenode.path))}
${h.checkbox('',checked="checked",class_="show-inline-comments",id_for=h.FID(filenode.changeset.raw_id,filenode.path))}
</label>
</span>
@@ -164,7 +165,7 @@
<div class="comments-number">${len(c.comments)} comment(s) (${c.inline_cnt} ${_('inline')})</div>
%for path, lines in c.inline_comments:
<div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${self.fid(c.changeset.raw_id,path)}">
<div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${h.FID(c.changeset.raw_id,path)}">
% for line,comments in lines.iteritems():
<div class="inline-comment-placeholder-line" line="${line}" target_id="${h.safeid(h.safe_unicode(path))}">
%for co in comments:
Status change: