diff --git a/rhodecode/controllers/changeset.py b/rhodecode/controllers/changeset.py
--- a/rhodecode/controllers/changeset.py
+++ b/rhodecode/controllers/changeset.py
@@ -25,12 +25,18 @@
# along with this program. If not, see .
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 vcs.exceptions import RepositoryError, ChangesetError, \
- ChangesetDoesNotExistError
-from vcs.nodes import FileNode
-from webob.exc import HTTPForbidden
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:
+ if ig_ws is None:
+ params[fileid] += ['WS:1']
+ lbl = _('ignore white space')
+
+ 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))
+
+ if ln_ctx:
+ retval = ln_ctx[0].split(':')[-1]
+ else:
+ retval = ln_ctx_global
+
+ try:
+ return int(retval)
+ except:
+ return
+
+def _context_url(fileid=None):
+ """
+ Generates url for context lines
+
+ :param fileid:
+ """
+ ig_ws = get_ignore_ws(fileid, request.GET)
+ ln_ctx = (get_line_ctx(fileid, request.GET) or 3) * 2
+
+ params = defaultdict(list)
+
+ # global option
+ if fileid is None:
+ if ln_ctx > 0:
+ params['context'] += [ln_ctx]
+
+ if ig_ws:
+ ig_ws_key = 'ignorews'
+ ig_ws_val = 1
+
+ # per file option
+ else:
+ params[fileid] += ['C:%s' % ln_ctx]
+ ig_ws_key = fileid
+ ig_ws_val = 'WS:%s' % 1
+
+ if ig_ws:
+ params[ig_ws_key] += [ig_ws_val]
+
+ lbl = _('%s line context') % ln_ctx
+
+ params['anchor'] = fileid
+ return h.link_to(lbl, h.url.current(**params))
+
+def wrap_to_table(str_):
+ return '''
''' % 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):
- return '''''' % 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
else:
if c.sum_removed < self.cut_off_limit:
+ fid = h.FID(revision, node.path)
+ line_context_lcl = get_line_ctx(fid, request.GET)
+ ignore_whitespace_lcl = get_ignore_ws(fid, request.GET,)
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()
diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py
--- a/rhodecode/lib/helpers.py
+++ b/rhodecode/lib/helpers.py
@@ -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.
diff --git a/rhodecode/public/css/style.css b/rhodecode/public/css/style.css
--- a/rhodecode/public/css/style.css
+++ b/rhodecode/public/css/style.css
@@ -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{
text-decoration: none;
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;
diff --git a/rhodecode/templates/changeset/changeset.html b/rhodecode/templates/changeset/changeset.html
--- a/rhodecode/templates/changeset/changeset.html
+++ b/rhodecode/templates/changeset/changeset.html
@@ -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>
-
<%def name="main()">
@@ -33,19 +27,24 @@
-
${_('commit')} ${c.changeset.revision}: ${h.short_id(c.changeset.raw_id)}@${c.changeset.date}
,20)})
@@ -100,9 +99,9 @@
%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
${h.fancy_file_stats(stat)}
@@ -118,8 +117,8 @@
%for change,filenode,diff,cs1,cs2,stat in c.changes:
%if change !='removed':
-
-
+
+
@@ -164,7 +165,7 @@
%for path, lines in c.inline_comments:
-