################################################################################
# RhodeCode - Pylons environment configuration #
# #
# The %(here)s variable will be replaced with the parent directory of this file#
[DEFAULT]
debug = true
## 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 =
#smtp_server = mail.server.com
#smtp_username =
#smtp_password =
#smtp_port =
#smtp_use_tls = false
#smtp_use_ssl = true
[server:main]
##nr of threads to spawn
threadpool_workers = 5
##max request before thread respawn
threadpool_max_requests = 6
##option to use threads of process
use_threadpool = false
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
cut_off_limit = 256000
####################################
### 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 = 3
#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.short_term.type=memory
beaker.cache.short_term.expire=60
beaker.cache.long_term.type=memory
beaker.cache.long_term.expire=36000
beaker.cache.sql_cache_short.type=memory
beaker.cache.sql_cache_short.expire=10
beaker.cache.sql_cache_med.type=memory
# rhodecode - Pylons environment configuration #
## Additionally those settings will be used by rhodecode mailing system ##
threadpool_max_requests = 2
use_threadpool = true
host = 127.0.0.1
port = 8001
static_files = false
beaker.cache.sql_cache_short.expire=5
threadpool_max_requests = 10
app_instance_uuid = ${app_instance_uuid}
#!/usr/bin/env python
# encoding: utf-8
# changeset controller for pylons
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
# -*- coding: utf-8 -*-
"""
rhodecode.controllers.changeset
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
changeset controller for pylons
:created_on: Apr 25, 2010
:author: marcink
:copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
: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; version 2
# of the License or (at your opinion) any later version of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
Created on April 25, 2010
@author: marcink
import logging
import traceback
from pylons import tmpl_context as c, url, request, response
from pylons.i18n.translation import _
from pylons.controllers.util import redirect
import rhodecode.lib.helpers as h
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
from rhodecode.lib.base import BaseController, render
from rhodecode.lib.utils import EmptyChangeset
from rhodecode.model.scm import ScmModel
from vcs.exceptions import RepositoryError, ChangesetError
from vcs.nodes import FileNode
from vcs.utils import diffs as differ
log = logging.getLogger(__name__)
class ChangesetController(BaseController):
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
'repository.admin')
def __before__(self):
super(ChangesetController, self).__before__()
def index(self, revision):
hg_model = ScmModel()
cut_off_limit = 1024 * 250
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
try:
c.changeset = hg_model.get_repo(c.repo_name).get_changeset(revision)
except RepositoryError, e:
log.error(traceback.format_exc())
h.flash(str(e), category='warning')
return redirect(url('home'))
else:
c.changeset_old = c.changeset.parents[0]
except IndexError:
c.changeset_old = None
c.changes = []
#===================================================================
# ADDED FILES
c.sum_added = 0
for node in c.changeset.added:
filenode_old = FileNode(node.path, '', EmptyChangeset())
if filenode_old.is_binary or node.is_binary:
diff = wrap_to_table(_('binary file'))
c.sum_added += node.size
if c.sum_added < cut_off_limit:
if c.sum_added < self.cut_off_limit:
f_udiff = differ.get_udiff(filenode_old, node)
diff = differ.DiffProcessor(f_udiff).as_html()
diff = wrap_to_table(_('Changeset is to big and was cut'
' off, see raw changeset instead'))
cs1 = None
cs2 = node.last_changeset.raw_id
c.changes.append(('added', node, diff, cs1, cs2))
# CHANGED FILES
c.sum_removed = 0
for node in c.changeset.changed:
filenode_old = c.changeset_old.get_node(node.path)
except ChangesetError:
if c.sum_removed < cut_off_limit:
if c.sum_removed < self.cut_off_limit:
if diff:
c.sum_removed += len(diff)
cs1 = filenode_old.last_changeset.raw_id
c.changes.append(('changed', node, diff, cs1, cs2))
# REMOVED FILES
for node in c.changeset.removed:
c.changes.append(('removed', node, None, None, None))
return render('changeset/changeset.html')
def raw_changeset(self, revision):
method = request.GET.get('diff', 'show')
r = hg_model.get_repo(c.repo_name)
c.scm_type = r.alias
c.changeset = r.get_changeset(revision)
except RepositoryError:
filenode_old = FileNode(node.path, '')
diff = _('binary file') +'\n'
diff = _('binary file') + '\n'
diff = differ.DiffProcessor(f_udiff).raw_diff()
diff = _('binary file')
response.content_type = 'text/plain'
if method == 'download':
response.content_disposition = 'attachment; filename=%s.patch' % revision
parent = True if len(c.changeset.parents) > 0 else False
c.parent_tmpl = 'Parent %s' % c.changeset.parents[0].raw_id if parent else ''
c.diffs = ''
for x in c.changes:
c.diffs += x[2]
return render('changeset/raw_changeset.html')
# files controller for pylons
rhodecode.controllers.files
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Files controller for RhodeCode
:created_on: Apr 21, 2010
Created on April 21, 2010
files controller for pylons
import tempfile
from mercurial import archival
from pylons import request, response, session, tmpl_context as c, url
class FilesController(BaseController):
super(FilesController, self).__before__()
c.file_size_limit = 250 * 1024 #limit of file size to display
def index(self, repo_name, revision, f_path):
c.repo = hg_model.get_repo(c.repo_name)
revision = request.POST.get('at_rev', None) or revision
def get_next_rev(cur):
max_rev = len(c.repo.revisions) - 1
r = cur + 1
if r > max_rev:
r = max_rev
return r
def get_prev_rev(cur):
r = cur - 1
c.f_path = f_path
c.changeset = c.repo.get_changeset(revision)
cur_rev = c.changeset.revision
prev_rev = c.repo.get_changeset(get_prev_rev(cur_rev)).raw_id
next_rev = c.repo.get_changeset(get_next_rev(cur_rev)).raw_id
c.url_prev = url('files_home', repo_name=c.repo_name,
revision=prev_rev, f_path=f_path)
c.url_next = url('files_home', repo_name=c.repo_name,
revision=next_rev, f_path=f_path)
c.files_list = c.changeset.get_node(f_path)
c.file_history = self._get_history(c.repo, c.files_list, f_path)
redirect(h.url('files_home', repo_name=repo_name, revision=revision))
redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
return render('files/files.html')
def rawfile(self, repo_name, revision, f_path):
@@ -152,96 +157,96 @@ class FilesController(BaseController):
prefix='%s-%s' % (repo_name, revision))
response.content_type = archive_specs[fileformat][0]
response.content_disposition = 'attachment; filename=%s' % fname
archive.seek(0)
return read_in_chunks(archive)
def diff(self, repo_name, f_path):
diff1 = request.GET.get('diff1')
diff2 = request.GET.get('diff2')
c.action = request.GET.get('diff')
c.no_changes = diff1 == diff2
if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
c.changeset_1 = c.repo.get_changeset(diff1)
node1 = c.changeset_1.get_node(f_path)
c.changeset_1 = EmptyChangeset()
node1 = FileNode('.', '', changeset=c.changeset_1)
if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
c.changeset_2 = c.repo.get_changeset(diff2)
node2 = c.changeset_2.get_node(f_path)
c.changeset_2 = EmptyChangeset()
node2 = FileNode('.', '', changeset=c.changeset_2)
return redirect(url('files_home',
repo_name=c.repo_name, f_path=f_path))
f_udiff = differ.get_udiff(node1, node2)
diff = differ.DiffProcessor(f_udiff)
if c.action == 'download':
diff_name = '%s_vs_%s.diff' % (diff1, diff2)
response.content_disposition = 'attachment; filename=%s' \
% diff_name
return diff.raw_diff()
elif c.action == 'raw':
elif c.action == 'diff':
if node1.size > c.file_size_limit or node2.size > c.file_size_limit:
if node1.size > self.cut_off_limit or node2.size > self.cut_off_limit:
c.cur_diff = _('Diff is to big to display')
c.cur_diff = diff.as_html()
#default option
if not c.cur_diff: c.no_changes = True
return render('files/file_diff.html')
def _get_history(self, repo, node, f_path):
from vcs.nodes import NodeKind
if not node.kind is NodeKind.FILE:
return []
changesets = node.history
hist_l = []
changesets_group = ([], _("Changesets"))
branches_group = ([], _("Branches"))
tags_group = ([], _("Tags"))
for chs in changesets:
n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
changesets_group[0].append((chs.raw_id, n_desc,))
hist_l.append(changesets_group)
for name, chs in c.repository_branches.items():
#chs = chs.split(':')[-1]
branches_group[0].append((chs, name),)
hist_l.append(branches_group)
for name, chs in c.repository_tags.items():
tags_group[0].append((chs, name),)
hist_l.append(tags_group)
return hist_l
# [
# ([("u1", "User1"), ("u2", "User2")], "Users"),
# ([("g1", "Group1"), ("g2", "Group2")], "Groups")
# ]
"""The base Controller API
Provides the BaseController class for subclassing.
from pylons import config, tmpl_context as c, request, session
from pylons.controllers import WSGIController
from pylons.templating import render_mako as render
from rhodecode import __version__
from rhodecode.lib import auth
from rhodecode.lib.utils import get_repo_slug
from rhodecode.model import meta
from rhodecode import BACKENDS
class BaseController(WSGIController):
c.rhodecode_version = __version__
c.rhodecode_name = config['rhodecode_title']
c.repo_name = get_repo_slug(request)
c.cached_repo_list = ScmModel().get_repos()
c.backends = BACKENDS.keys()
self.cut_off_limit = int(config['cut_off_limit'])
self.sa = meta.Session()
scm_model = ScmModel(self.sa)
#c.unread_journal = scm_model.get_unread_journal()
if c.repo_name:
cached_repo = scm_model.get(c.repo_name)
if cached_repo:
c.repository_tags = cached_repo.tags
c.repository_branches = cached_repo.branches
c.repository_followers = scm_model.get_followers(cached_repo.dbrepo.repo_id)
c.repository_forks = scm_model.get_forks(cached_repo.dbrepo.repo_id)
c.repository_tags = {}
c.repository_branches = {}
c.repository_followers = 0
c.repository_forks = 0
def __call__(self, environ, start_response):
"""Invoke the Controller"""
# WSGIController.__call__ dispatches to the Controller method
# the request is routed to. This routing information is
# available in environ['pylons.routes_dict']
#putting this here makes sure that we update permissions every time
self.rhodecode_user = c.rhodecode_user = auth.get_user(session)
return WSGIController.__call__(self, environ, start_response)
finally:
meta.Session.remove()
index_dir = /tmp/index
Status change: