# -*- coding: utf-8 -*-
"""
rhodecode.lib.diffs
~~~~~~~~~~~~~~~~~~~
Set of diffing helpers, previously part of vcs
:created_on: Dec 4, 2011
:author: marcink
:copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
:original copyright: 2007-2008 by Armin Ronacher
:license: GPLv3, see COPYING for more details.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
@@ -27,21 +27,21 @@
import re
import difflib
from itertools import tee, imap
from mercurial.match import match
from vcs.exceptions import VCSError
from vcs.nodes import FileNode
import markupsafe
def get_gitdiff(filenode_old, filenode_new, ignore_whitespace=True, context=3):
Returns git style diff between given ``filenode_old`` and ``filenode_new``.
:param ignore_whitespace: ignore whitespaces in diff
for filenode in (filenode_old, filenode_new):
if not isinstance(filenode, FileNode):
raise VCSError("Given object should be FileNode object, not %s"
@@ -92,13 +92,13 @@ class DiffProcessor(object):
if differ == 'difflib':
self.differ = self._highlight_line_difflib
else:
self.differ = self._highlight_line_udiff
def escaper(self, string):
return string.replace('<', '<').replace('>', '>')
return markupsafe.escape(string)
def copy_iterator(self):
make a fresh copy of generator, we should not iterate thru
an original as it's needed for repeating operations on
this instance of DiffProcessor
@@ -150,21 +150,21 @@ class DiffProcessor(object):
return map(line_decoder, output[0].splitlines(1))
elif size == 0:
return []
raise Exception('wrong size of diff %s' % size)
def _highlight_line_difflib(self, line, next):
def _highlight_line_difflib(self, line, next_):
Highlight inline changes in both lines.
if line['action'] == 'del':
old, new = line, next
old, new = line, next_
old, new = next, line
old, new = next_, line
oldwords = re.split(r'(\W)', old['line'])
newwords = re.split(r'(\W)', new['line'])
sequence = difflib.SequenceMatcher(None, oldwords, newwords)
@@ -180,23 +180,23 @@ class DiffProcessor(object):
oldfragments.append(oldfrag)
newfragments.append(newfrag)
old['line'] = "".join(oldfragments)
new['line'] = "".join(newfragments)
def _highlight_line_udiff(self, line, next):
def _highlight_line_udiff(self, line, next_):
start = 0
limit = min(len(line['line']), len(next['line']))
while start < limit and line['line'][start] == next['line'][start]:
limit = min(len(line['line']), len(next_['line']))
while start < limit and line['line'][start] == next_['line'][start]:
start += 1
end = -1
limit -= start
while -end <= limit and line['line'][end] == next['line'][end]:
while -end <= limit and line['line'][end] == next_['line'][end]:
end -= 1
end += 1
if start or end:
def do(l):
last = end + len(l['line'])
if l['action'] == 'add':
@@ -208,13 +208,13 @@ class DiffProcessor(object):
tag,
l['line'][start:last],
l['line'][last:]
)
do(line)
do(next)
do(next_)
def _parse_udiff(self):
Parse the diff an return data for the template.
lineiter = self.lines
@@ -299,13 +299,13 @@ class DiffProcessor(object):
line = lineiter.next()
except StopIteration:
pass
# highlight inline changes
for file in files:
for _ in files:
for chunk in chunks:
lineiter = iter(chunk)
#first = True
try:
while 1:
@@ -211,55 +211,65 @@ def pygmentize(filenode, **kwargs):
:param filenode:
return literal(code_highlight(filenode.content,
filenode.lexer, CodeHtmlFormatter(**kwargs)))
def pygmentize_annotation(repo_name, filenode, **kwargs):
"""pygmentize function for annotation
pygmentize function for annotation
color_dict = {}
def gen_color(n=10000):
"""generator for getting n of evenly distributed colors using
hsv color and golden ratio. It always return same order of colors
:returns: RGB tuple
def hsv_to_rgb(h, s, v):
if s == 0.0: return v, v, v
i = int(h * 6.0) # XXX assume int() truncates!
if s == 0.0:
return v, v, v
f = (h * 6.0) - i
p = v * (1.0 - s)
q = v * (1.0 - s * f)
t = v * (1.0 - s * (1.0 - f))
i = i % 6
if i == 0: return v, t, p
if i == 1: return q, v, p
if i == 2: return p, v, t
if i == 3: return p, q, v
if i == 4: return t, p, v
if i == 5: return v, p, q
if i == 0:
return v, t, p
if i == 1:
return q, v, p
if i == 2:
return p, v, t
if i == 3:
return p, q, v
if i == 4:
return t, p, v
if i == 5:
return v, p, q
golden_ratio = 0.618033988749895
h = 0.22717784590367374
for _ in xrange(n):
h += golden_ratio
h %= 1
HSV_tuple = [h, 0.95, 0.95]
RGB_tuple = hsv_to_rgb(*HSV_tuple)
yield map(lambda x:str(int(x * 256)), RGB_tuple)
yield map(lambda x: str(int(x * 256)), RGB_tuple)
cgenerator = gen_color()
def get_color_string(cs):
if color_dict.has_key(cs):
if cs in color_dict:
col = color_dict[cs]
col = color_dict[cs] = cgenerator.next()
return "color: rgb(%s)! important;" % (', '.join(col))
def url_func(repo_name):
@@ -288,12 +298,13 @@ def pygmentize_annotation(repo_name, fil
uri += '\n'
return uri
return _url_func
return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
def is_following_repo(repo_name, user_id):
from rhodecode.model.scm import ScmModel
return ScmModel().is_following_repo(repo_name, user_id)
flash = _Flash()
@@ -301,13 +312,13 @@ flash = _Flash()
# SCM FILTERS available via h.
#==============================================================================
from vcs.utils import author_name, author_email
from rhodecode.lib import credentials_filter, age as _age
from rhodecode.model.db import User
age = lambda x:_age(x)
age = lambda x: _age(x)
capitalize = lambda x: x.capitalize()
email = author_email
short_id = lambda x: x[:12]
hide_credentials = lambda x: ''.join(credentials_filter(x))
@@ -322,16 +333,17 @@ def email_or_none(author):
if user is not None:
return user.email
# No valid email, not a valid user in the system, none!
return None
def person(author):
# attr to return from fetched user
person_getter = lambda usr: usr.username
# Valid email in the attribute passed, see if they're in the system
_email = email(author)
if _email != '':
user = User.get_by_email(_email, case_insensitive=True, cache=True)
return person_getter(user)
Status change: