################################################################################
# RhodeCode - Pylons environment configuration #
# #
# The %(here)s variable will be replaced with the parent directory of this file#
[DEFAULT]
debug = true
pdebug = false
## Uncomment and replace with the address which should receive ##
## any error reports after application crash ##
## Additionally those settings will be used by RhodeCode mailing system ##
#email_to = admin@localhost
#error_email_from = paste_error@localhost
#app_email_from = rhodecode-noreply@localhost
#error_message =
#email_prefix = [RhodeCode]
#smtp_server = mail.server.com
#smtp_username =
#smtp_password =
#smtp_port =
#smtp_use_tls = false
#smtp_use_ssl = true
# Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
#smtp_auth =
[server:main]
##nr of threads to spawn
threadpool_workers = 5
##max request before thread respawn
threadpool_max_requests = 10
##option to use threads of process
use_threadpool = true
use = egg:Paste#http
host = 0.0.0.0
port = 5000
[app:main]
use = egg:rhodecode
full_stack = true
static_files = true
lang=en
cache_dir = %(here)s/data
index_dir = %(here)s/data/index
app_instance_uuid = develop
cut_off_limit = 256000
force_https = false
commit_parse_limit = 25
use_gravatar = true
container_auth_enabled = false
proxypass_auth_enabled = false
## overwrite schema of clone url
# available vars:
# scheme - http/https
# user - current user
# pass - password
# netloc - network location
# path - usually repo_name
# clone_uri = {scheme}://{user}{pass}{netloc}{path}
## available vars:
## scheme - http/https
## user - current user
## pass - password
## netloc - network location
## path - usually repo_name
#clone_uri = {scheme}://{user}{pass}{netloc}{path}
## issue tracking mapping for commits messages
## uncomment url_pat, issue_server, issue_prefix to enable
## pattern to get the issues from commit messages
## default one used here is #1234
#url_pat = (?:^#|\s#)(\w+)
## server url to the issue, each {id} will be replaced with id
## fetched from the regex
#issue_server = https://myissueserver.com/issue/{id}
## prefix to add to link to indicate it's an url
## #314 will be replaced by <issue_prefix><id>
#issue_prefix = #
####################################
### CELERY CONFIG ####
use_celery = false
broker.host = localhost
broker.vhost = rabbitmqhost
broker.port = 5672
broker.user = rabbitmq
broker.password = qweqwe
celery.imports = rhodecode.lib.celerylib.tasks
celery.result.backend = amqp
celery.result.dburi = amqp://
celery.result.serialier = json
#celery.send.task.error.emails = true
#celery.amqp.task.result.expires = 18000
celeryd.concurrency = 2
#celeryd.log.file = celeryd.log
celeryd.log.level = debug
celeryd.max.tasks.per.child = 1
#tasks will never be sent to the queue, but executed locally instead.
celery.always.eager = false
### BEAKER CACHE ####
beaker.cache.data_dir=%(here)s/data/cache/data
beaker.cache.lock_dir=%(here)s/data/cache/lock
beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
beaker.cache.super_short_term.type=memory
beaker.cache.super_short_term.expire=10
beaker.cache.super_short_term.key_length = 256
beaker.cache.short_term.type=memory
beaker.cache.short_term.expire=60
beaker.cache.short_term.key_length = 256
beaker.cache.long_term.type=memory
beaker.cache.long_term.expire=36000
beaker.cache.long_term.key_length = 256
beaker.cache.sql_cache_short.type=memory
beaker.cache.sql_cache_short.expire=10
beaker.cache.sql_cache_short.key_length = 256
beaker.cache.sql_cache_med.type=memory
beaker.cache.sql_cache_med.expire=360
beaker.cache.sql_cache_med.key_length = 256
beaker.cache.sql_cache_long.type=file
beaker.cache.sql_cache_long.expire=3600
beaker.cache.sql_cache_long.key_length = 256
### BEAKER SESSION ####
## Type of storage used for the session, current types are
## dbm, file, memcached, database, and memory.
## The storage uses the Container API
## that is also used by the cache system.
## db session example
#beaker.session.type = ext:database
#beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
#beaker.session.table_name = db_session
## encrypted cookie session, good for many instances
#beaker.session.type = cookie
beaker.session.type = file
beaker.session.key = rhodecode
#beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
#beaker.session.validate_key = 9712sds2212c--zxc123
beaker.session.timeout = 36000
beaker.session.httponly = true
## uncomment for https secure cookie
beaker.session.secure = false
##auto save the session to not to use .save()
beaker.session.auto = False
##true exire at browser close
#beaker.session.cookie_expires = 3600
## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
host = 127.0.0.1
port = 8001
app_instance_uuid = prod1234
commit_parse_limit = 50
app_instance_uuid = ${app_instance_uuid}
beaker.session.encrypt_key = ${app_instance_secret}
beaker.session.validate_key = ${app_instance_secret}
## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
"""Helper functions
Consists of functions to typically be used within templates, but also
available to Controllers. This module is available to both as 'h'.
"""
import random
import hashlib
import StringIO
import urllib
import math
import logging
from datetime import datetime
from pygments.formatters.html import HtmlFormatter
from pygments import highlight as code_highlight
from pylons import url, request, config
from pylons.i18n.translation import _, ungettext
from hashlib import md5
from webhelpers.html import literal, HTML, escape
from webhelpers.html.tools import *
from webhelpers.html.builder import make_tag
from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
end_form, file, form, hidden, image, javascript_link, link_to, \
link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
submit, text, password, textarea, title, ul, xml_declaration, radio
from webhelpers.html.tools import auto_link, button_to, highlight, \
js_obfuscate, mail_to, strip_links, strip_tags, tag_re
from webhelpers.number import format_byte_size, format_bit_size
from webhelpers.pylonslib import Flash as _Flash
from webhelpers.pylonslib.secure_form import secure_form
from webhelpers.text import chop_at, collapse, convert_accented_entities, \
convert_misc_entities, lchop, plural, rchop, remove_formatting, \
replace_whitespace, urlify, truncate, wrap_paragraphs
from webhelpers.date import time_ago_in_words
from webhelpers.paginate import Page
from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
convert_boolean_attrs, NotGiven, _make_safe_id_component
from rhodecode.lib.annotate import annotate_highlight
from rhodecode.lib.utils import repo_name_slug
from rhodecode.lib import str2bool, safe_unicode, safe_str, get_changeset_safe
from rhodecode.lib.markup_renderer import MarkupRenderer
log = logging.getLogger(__name__)
def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
Reset button
_set_input_attrs(attrs, type, name, value)
_set_id_attr(attrs, id, name)
convert_boolean_attrs(attrs, ["disabled"])
return HTML.input(**attrs)
reset = _reset
safeid = _make_safe_id_component
def FID(raw_id, path):
Creates a uniqe ID for filenode based on it's hash of path and revision
it's safe to use in urls
:param raw_id:
:param path:
return 'C-%s-%s' % (short_id(raw_id), md5(path).hexdigest()[:12])
def get_token():
"""Return the current authentication token, creating one if one doesn't
already exist.
token_key = "_authentication_token"
from pylons import session
if not token_key in session:
try:
token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
except AttributeError: # Python < 2.4
token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
session[token_key] = token
if hasattr(session, 'save'):
session.save()
return session[token_key]
class _GetError(object):
"""Get error from form_errors, and represent it as span wrapped error
message
:param field_name: field to fetch errors for
:param form_errors: form errors dict
def __call__(self, field_name, form_errors):
tmpl = """<span class="error_msg">%s</span>"""
if form_errors and form_errors.has_key(field_name):
return literal(tmpl % form_errors.get(field_name))
get_error = _GetError()
class _ToolTip(object):
def __call__(self, tooltip_title, trim_at=50):
"""Special function just to wrap our text into nice formatted
autowrapped text
:param tooltip_title:
return escape(tooltip_title)
tooltip = _ToolTip()
class _FilesBreadCrumbs(object):
def __call__(self, repo_name, rev, paths):
if isinstance(paths, str):
paths = safe_unicode(paths)
url_l = [link_to(repo_name, url('files_home',
repo_name=repo_name,
revision=rev, f_path=''))]
paths_l = paths.split('/')
for cnt, p in enumerate(paths_l):
if p != '':
url_l.append(link_to(p,
url('files_home',
revision=rev,
f_path='/'.join(paths_l[:cnt + 1])
)
return literal('/'.join(url_l))
files_breadcrumbs = _FilesBreadCrumbs()
class CodeHtmlFormatter(HtmlFormatter):
"""My code Html Formatter for source codes
@@ -647,109 +650,136 @@ def changed_tooltip(nodes):
for x in nodes[:30]]) + suf)
else:
return ': ' + _('No Files')
def repo_link(groups_and_repos):
Makes a breadcrumbs link to repo within a group
joins » on each group to create a fancy link
ex::
group >> subgroup >> repo
:param groups_and_repos:
groups, repo_name = groups_and_repos
if not groups:
return repo_name
def make_link(group):
return link_to(group.name, url('repos_group_home',
group_name=group.group_name))
return literal(' » '.join(map(make_link, groups)) + \
" » " + repo_name)
def fancy_file_stats(stats):
Displays a fancy two colored bar for number of added/deleted
lines of code on file
:param stats: two element list of added/deleted lines of code
a, d, t = stats[0], stats[1], stats[0] + stats[1]
width = 100
unit = float(width) / (t or 1)
# needs > 9% of width to be visible or 0 to be hidden
a_p = max(9, unit * a) if a > 0 else 0
d_p = max(9, unit * d) if d > 0 else 0
p_sum = a_p + d_p
if p_sum > width:
#adjust the percentage to be == 100% since we adjusted to 9
if a_p > d_p:
a_p = a_p - (p_sum - width)
d_p = d_p - (p_sum - width)
a_v = a if a > 0 else ''
d_v = d if d > 0 else ''
def cgen(l_type):
mapping = {'tr':'top-right-rounded-corner',
'tl':'top-left-rounded-corner',
'br':'bottom-right-rounded-corner',
'bl':'bottom-left-rounded-corner'}
map_getter = lambda x:mapping[x]
if l_type == 'a' and d_v:
#case when added and deleted are present
return ' '.join(map(map_getter, ['tl', 'bl']))
if l_type == 'a' and not d_v:
return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
if l_type == 'd' and a_v:
return ' '.join(map(map_getter, ['tr', 'br']))
if l_type == 'd' and not a_v:
d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (cgen('a'),
a_p, a_v)
d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (cgen('d'),
d_p, d_v)
return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
def urlify_text(text):
import re
url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'''
'''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
def url_func(match_obj):
url_full = match_obj.groups()[0]
return '<a href="%(url)s">%(url)s</a>' % ({'url':url_full})
return literal(url_pat.sub(url_func, text))
def urlify_commit(text):
import traceback
conf = config['app_conf']
URL_PAT = re.compile(r'%s' % conf.get('url_pat'))
if URL_PAT:
ISSUE_SERVER = conf.get('issue_server')
ISSUE_PREFIX = conf.get('issue_prefix')
issue_id = match_obj.groups()[0]
return ' <a href="%(url)s">%(issue-prefix)s%(id-repr)s</a>' % (
{'url':ISSUE_SERVER.replace('{id}',issue_id),
'id-repr':issue_id,
'issue-prefix':ISSUE_PREFIX,
'serv':ISSUE_SERVER,
}
return literal(URL_PAT.sub(url_func, text))
except:
log.error(traceback.format_exc())
pass
return text
def rst(source):
return literal('<div class="rst-block">%s</div>' %
MarkupRenderer.rst(source))
def rst_w_mentions(source):
Wrapped rst renderer with @mention highlighting
:param source:
MarkupRenderer.rst_with_mentions(source))
@@ -2053,194 +2053,192 @@ div.form div.fields div.field div.button
#journal .date {
clear: both;
color: #777777;
font-size: 11px;
padding-left: 22px;
#journal .journal_repo .journal_repo_name {
font-weight: bold;
font-size: 1.1em;
#journal .compare_view {
padding: 5px 0px 5px 0px;
width: 95px;
.journal_highlight {
padding: 0 2px;
vertical-align: bottom;
.trending_language_tbl,.trending_language_tbl td {
border: 0 !important;
margin: 0 !important;
padding: 0 !important;
.trending_language_tbl,.trending_language_tbl tr {
border-spacing: 1px;
.trending_language {
background-color: #003367;
color: #FFF;
display: block;
min-width: 20px;
text-decoration: none;
height: 12px;
margin-bottom: 0px;
margin-left: 5px;
white-space: pre;
padding: 3px;
h3.files_location {
font-size: 1.8em;
font-weight: 700;
border-bottom: none !important;
margin: 10px 0 !important;
#files_data dl dt {
float: left;
width: 60px;
padding: 5px;
#files_data dl dd {
padding: 5px !important;
#changeset_content {
border: 1px solid #CCC;
#changeset_compare_view_content {
#changeset_content .container {
min-height: 120px;
font-size: 1.2em;
overflow: hidden;
#changeset_compare_view_content .compare_view_commits {
width: auto !important;
#changeset_compare_view_content .compare_view_commits td {
padding: 0px 0px 0px 12px !important;
#changeset_content .container .right {
float: right;
width: 25%;
text-align: right;
#changeset_content .container .left .message {
font-style: italic;
color: #556CB5;
white-space: pre-wrap;
#changeset_content .container .left .message a:hover {
.cs_files .cur_cs {
margin: 10px 2px;
.cs_files .node {
.cs_files .changes {
color:#003367;
.cs_files .changes .added {
background-color: #BBFFBB;
text-align: center;
font-size: 9px;
padding: 2px 0px 2px 0px;
.cs_files .changes .deleted {
background-color: #FF8888;
.cs_files .cs_added {
background: url("../images/icons/page_white_add.png") no-repeat scroll
3px;
height: 16px;
padding-left: 20px;
margin-top: 7px;
text-align: left;
.cs_files .cs_changed {
background: url("../images/icons/page_white_edit.png") no-repeat scroll
.cs_files .cs_removed {
background: url("../images/icons/page_white_delete.png") no-repeat
scroll 3px;
#graph {
#graph_nodes {
margin-right: -6px;
margin-top: 0px;
#graph_content {
width: 800px;
#graph_content .container_header {
padding: 10px;
height: 45px;
-webkit-border-radius: 6px 6px 0px 0px;
-moz-border-radius: 6px 6px 0px 0px;
border-radius: 6px 6px 0px 0px;
#graph_content #rev_range_container {
padding: 10px 0px;
#graph_content .container {
border-bottom: 1px solid #CCC;
border-left: 1px solid #CCC;
border-right: 1px solid #CCC;
## -*- coding: utf-8 -*-
<%inherit file="/base/base.html"/>
<%def name="title()">
${c.repo_name} ${_('Changelog')} - ${c.rhodecode_name}
</%def>
<%def name="breadcrumbs_links()">
${h.link_to(u'Home',h.url('/'))}
»
${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
${_('Changelog')} - ${_('showing ')} ${c.size if c.size <= c.total_cs else c.total_cs} ${_('out of')} ${c.total_cs} ${_('revisions')}
<%def name="page_nav()">
${self.menu('changelog')}
<%def name="main()">
<div class="box">
<!-- box / title -->
<div class="title">
${self.breadcrumbs()}
</div>
<div class="table">
% if c.pagination:
<div id="graph">
<div id="graph_nodes">
<canvas id="graph_canvas"></canvas>
<div id="graph_content">
<div class="container_header">
${h.form(h.url.current(),method='get')}
<div class="info_box" style="float:left">
${h.submit('set',_('Show'),class_="ui-btn")}
${h.text('size',size=1,value=c.size)}
<span class="rev">${_('revisions')}</span>
${h.end_form()}
<div style="float:right">${h.select('branch_filter',c.branch_name,c.branch_filters)}</div>
<div id="rev_range_container" style="display:none"></div>
%for cnt,cs in enumerate(c.pagination):
<div id="chg_${cnt+1}" class="container">
<div class="left">
<div class="date">
${h.checkbox(cs.short_id,class_="changeset_range")}
<span>${_('commit')} ${cs.revision}: ${h.short_id(cs.raw_id)}@${cs.date}</span>
<span class="tooltip" title="${cs.date}"><a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}">${cs.revision}:${h.short_id(cs.raw_id)}</a></span>
<div class="author">
<div class="gravatar">
<img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),16)}"/>
<div title="${cs.author}" class="user">${h.person(cs.author)}</div>
<div class="message">${h.link_to(h.wrap_paragraphs(cs.message),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
<div class="message">${h.urlify_commit(h.wrap_paragraphs(cs.message))}</div>
<div class="right">
<div id="${cs.raw_id}_changes_info" class="changes">
<span id="${cs.raw_id}" class="changed_total tooltip" title="${_('Affected number of files, click to show more details')}">${len(cs.affected_files)}</span>
%if len(cs.parents)>1:
<div class="merge">${_('merge')}</div>
%endif
%if cs.parents:
%for p_cs in reversed(cs.parents):
<div class="parent">${_('Parent')} ${p_cs.revision}: ${h.link_to(h.short_id(p_cs.raw_id),
h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}
%endfor
%else:
<div class="parent">${_('No parents')}</div>
<span class="logtags">
%if cs.branch:
<span class="branchtag" title="${'%s %s' % (_('branch'),cs.branch)}">
${h.link_to(cs.branch,h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}</span>
%for tag in cs.tags:
<span class="tagtag" title="${'%s %s' % (_('tag'),tag)}">
${h.link_to(tag,h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}</span>
</span>
<div class="pagination-wh pagination-left">
${c.pagination.pager('$link_previous ~2~ $link_next')}
<script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
<script type="text/javascript">
YAHOO.util.Event.onDOMReady(function(){
//Monitor range checkboxes and build a link to changesets
//ranges
var checkboxes = YUD.getElementsByClassName('changeset_range');
var url_tmpl = "${h.url('changeset_home',repo_name=c.repo_name,revision='__REVRANGE__')}";
YUE.on(checkboxes,'click',function(e){
var checked_checkboxes = [];
for (pos in checkboxes){
if(checkboxes[pos].checked){
checked_checkboxes.push(checkboxes[pos]);
if(checked_checkboxes.length>1){
var rev_end = checked_checkboxes[0].name;
var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
var url = url_tmpl.replace('__REVRANGE__',
rev_start+'...'+rev_end);
var link = "<a href="+url+">${_('Show selected changes __S -> __E')}</a>"
link = link.replace('__S',rev_start);
link = link.replace('__E',rev_end);
YUD.get('rev_range_container').innerHTML = link;
YUD.setStyle('rev_range_container','display','');
else{
YUD.setStyle('rev_range_container','display','none');
});
// Fetch changeset details
YUE.on(YUD.getElementsByClassName('changed_total'),'click',function(e){
var id = e.currentTarget.id
var url = "${h.url('changelog_details',repo_name=c.repo_name,cs='__CS__')}"
var url = url.replace('__CS__',id);
ypjax(url,id+'_changes_info',function(){tooltip_activate()});
// change branch filter
YUE.on(YUD.get('branch_filter'),'change',function(e){
var selected_branch = e.currentTarget.options[e.currentTarget.selectedIndex].value;
console.log(selected_branch);
var url_main = "${h.url('changelog_home',repo_name=c.repo_name)}";
var url = "${h.url('changelog_home',repo_name=c.repo_name,branch='__BRANCH__')}";
var url = url.replace('__BRANCH__',selected_branch);
if(selected_branch != ''){
window.location = url;
}else{
window.location = url_main;
function set_canvas(heads) {
${c.repo_name} ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} - ${c.rhodecode_name}
${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
<div class="diffblock">
<div class="code-header">
<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 class="comments-number" style="float:right;padding-right:5px">${len(c.comments)} comment(s) (${c.inline_cnt} ${_('inline')})</div>
<div id="changeset_content">
<div class="container">
<img alt="gravatar" src="${h.gravatar_url(h.email(c.changeset.author),20)}"/>
<span>${h.person(c.changeset.author)}</span><br/>
<span><a href="mailto:${h.email_or_none(c.changeset.author)}">${h.email_or_none(c.changeset.author)}</a></span><br/>
<div class="message">${h.link_to(h.wrap_paragraphs(c.changeset.message),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</div>
<div class="message">${h.urlify_commit(h.wrap_paragraphs(c.changeset.message))}</div>
<div class="changes">
% if len(c.changeset.affected_files) <= c.affected_files_cut_off:
<span class="removed" title="${_('removed')}">${len(c.changeset.removed)}</span>
<span class="changed" title="${_('changed')}">${len(c.changeset.changed)}</span>
<span class="added" title="${_('added')}">${len(c.changeset.added)}</span>
% else:
<span class="removed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
<span class="changed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
<span class="added" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
% endif
%if len(c.changeset.parents)>1:
<div class="merge">
${_('merge')}<img alt="merge" src="${h.url('/images/icons/arrow_join.png')}"/>
%if c.changeset.parents:
%for p_cs in reversed(c.changeset.parents):
<span class="branchtag" title="${'%s %s' % (_('branch'),c.changeset.branch)}">
${h.link_to(c.changeset.branch,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
%for tag in c.changeset.tags:
${h.link_to(tag,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
<span style="font-size:1.1em;font-weight: bold">
${_('%s files affected with %s additions and %s deletions.') % (len(c.changeset.affected_files),c.lines_added,c.lines_deleted)}
<div class="cs_files">
%for change,filenode,diff,cs1,cs2,stat in c.changes:
<div class="cs_${change}">
<div class="node">
%if change != 'removed':
${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path))}
${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID('',filenode.path)))}
<div class="changes">${h.fancy_file_stats(stat)}</div>
% if c.cut_off:
${_('Changeset was too big and was cut off...')}
## diff block
<%namespace name="diff_block" file="/changeset/diff_block.html"/>
${diff_block.diff_block(c.changes)}
## template for inline comment form
<%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
${comment.comment_inline_form(c.changeset)}
${comment.comments(c.changeset)}
var deleteComment = function(comment_id){
var url = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}".replace('__COMMENT_ID__',comment_id);
var postData = '_method=delete';
var success = function(o){
var n = YUD.get('comment-'+comment_id);
n.parentNode.removeChild(n);
ajaxPOST(url,postData,success);
YUE.onDOMReady(function(){
YUE.on(YUQ('.diff-menu-activate'),'click',function(e){
var act = e.currentTarget.nextElementSibling;
if(YUD.hasClass(act,'active')){
YUD.removeClass(act,'active');
YUD.setStyle(act,'display','none');
YUD.addClass(act,'active');
YUD.setStyle(act,'display','');
${c.repo_name} ${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)} - ${c.rhodecode_name}
${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)}
<div id="body" class="diffblock">
<div class="code-header cv">
<h3 class="code-header-title">${_('Compare View')}</h3>
<div>
<div id="changeset_compare_view_content">
<table class="compare_view_commits noborder">
%for cs in c.cs_ranges:
<tr>
<td><div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),14)}"/></div></td>
<td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</td>
<td><div class="author">${h.person(cs.author)}</div></td>
<td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td>
<td><div class="message">${h.link_to(h.wrap_paragraphs(cs.message),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div></td>
<td><div class="message">${h.urlify_commit(h.wrap_paragraphs(c.changeset.message))}</div></td>
</tr>
</table>
<div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div>
<div class="cur_cs">r${cs}</div>
%for change,filenode,diff,cs1,cs2,st in c.changes[cs.raw_id]:
<div class="cs_${change}">${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID(cs.raw_id,filenode.path)))}</div>
##${comment.comment_inline_form(cs)}
<h3 style="border:none;padding-top:8px;">${'r%s:%s' % (cs.revision,h.short_id(cs.raw_id))}</h3>
${diff_block.diff_block(c.changes[cs.raw_id])}
##${comment.comments(cs)}
})
</script>
\ No newline at end of file
%if c.repo_changesets:
<table class="table_disp">
<th class="left">${_('commit message')}</th>
<th class="left">${_('revision')}</th>
<th class="left">${_('age')}</th>
<th class="left">${_('author')}</th>
<th class="left">${_('branch')}</th>
<th class="left">${_('tags')}</th>
%for cnt,cs in enumerate(c.repo_changesets):
<tr class="parity${cnt%2}">
<td>
<div><pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre></div>
</td>
${h.link_to(h.truncate(cs.message,50),
h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id),
title=cs.message)}
<td><span class="tooltip" title="${cs.date}">
${h.age(cs.date)}</span>
<td title="${cs.author}">${h.person(cs.author)}</td>
<td><div><pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre></div></td>
<span class="branchtag">${cs.branch}</span>
<span class="tagtag">${tag}</span>
YUE.delegate("shortlog_data","click",function(e, matchedEl, container){
ypjax(e.target.href,"shortlog_data",function(){tooltip_activate();});
YUE.preventDefault(e);
},'.pager_link');
${c.repo_changesets.pager('$link_previous ~2~ $link_next')}
%if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
<h4>${_('Add or upload files directly via RhodeCode')}</h4>
<div style="margin: 20px 30px;">
<div id="add_node_id" class="add_node">
<a class="ui-btn" href="${h.url('files_add_home',repo_name=c.repo_name,revision=0,f_path='')}">${_('add new file')}</a>
<h4>${_('Push new repo')}</h4>
<pre>
${c.rhodecode_repo.alias} clone ${c.clone_repo_url}
${c.rhodecode_repo.alias} add README # add first file
${c.rhodecode_repo.alias} commit -m "Initial" # commit with message
${c.rhodecode_repo.alias} push # push changes back
</pre>
<h4>${_('Existing repository?')}</h4>
${c.rhodecode_repo.alias} push ${c.clone_repo_url}
Status change: