Mercurial > kallithea
changeset 1289:f56533aa1caa beta
Automated merge with https://rhodecode.org/rhodecode
author | "Lorenzo M. Catucci" <lorenzo@sancho.ccd.uniroma2.it> |
---|---|
date | Tue, 26 Apr 2011 14:03:00 +0200 |
parents | d6524f3025e8 (diff) a781d315191c (current diff) |
children | 74685a31cc43 |
files | |
diffstat | 45 files changed, 2790 insertions(+), 644 deletions(-) [+] |
line wrap: on
line diff
--- a/development.ini Tue Apr 26 14:02:53 2011 +0200 +++ b/development.ini Tue Apr 26 14:03:00 2011 +0200 @@ -141,8 +141,8 @@ ######################################################### ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ### ######################################################### -#sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db -sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode +sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db +#sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode sqlalchemy.db1.echo = True sqlalchemy.db1.pool_recycle = 3600 sqlalchemy.convert_unicode = true @@ -229,4 +229,4 @@ [formatter_color_formatter_sql] class=rhodecode.lib.colored_formatter.ColorFormatterSql format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %Y-%m-%d %H:%M:%S \ No newline at end of file +datefmt = %Y-%m-%d %H:%M:%S
--- a/init.d/rhodecode-daemon2 Tue Apr 26 14:02:53 2011 +0200 +++ b/init.d/rhodecode-daemon2 Tue Apr 26 14:03:00 2011 +0200 @@ -1,6 +1,6 @@ #!/bin/sh -e ######################################## -#### THIS IS AN DEBIAN INIT.D SCRIPT#### +#### THIS IS A DEBIAN INIT.D SCRIPT #### ######################################## ### BEGIN INIT INFO @@ -29,49 +29,48 @@ DAEMON="$PYTHON_PATH/bin/paster" DAEMON_OPTS="serve --daemon \ ---user=$RUN_AS \ ---group=$RUN_AS \ ---pid-file=$PID_PATH \ ---log-file=$LOG_PATH $APP_PATH/$CONF_NAME" + --user=$RUN_AS \ + --group=$RUN_AS \ + --pid-file=$PID_PATH \ + --log-file=$LOG_PATH $APP_PATH/$CONF_NAME" + +start() { + echo "Starting $APP_NAME" + PYTHON_EGG_CACHE="/tmp" start-stop-daemon -d $APP_PATH \ + --start --quiet \ + --pidfile $PID_PATH \ + --user $RUN_AS \ + --exec $DAEMON -- $DAEMON_OPTS +} + +stop() { + echo "Stopping $APP_NAME" + start-stop-daemon -d $APP_PATH \ + --stop --quiet \ + --pidfile $PID_PATH || echo "$APP_NAME - Not running!" + + if [ -f $PID_PATH ]; then + rm $PID_PATH + fi +} case "$1" in start) - echo "Starting $APP_NAME" - start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \ - --start --quiet \ - --pidfile $PID_PATH \ - --user $RUN_AS \ - --exec $DAEMON -- $DAEMON_OPTS + start ;; stop) - echo "Stopping $APP_NAME" - start-stop-daemon -d $APP_PATH \ - --stop --quiet \ - --pidfile $PID_PATH || echo "$APP_NAME - Not running!" - if [ -f $PID_PATH ]; then - rm $PID_PATH - fi + stop ;; restart) echo "Restarting $APP_NAME" ### stop ### - echo "Stopping $APP_NAME" - start-stop-daemon -d $APP_PATH \ - --stop --quiet \ - --pidfile $PID_PATH || echo "$APP_NAME - Not running!" - if [ -f $PID_PATH ]; then - rm $PID_PATH - fi + stop + wait ### start ### - echo "Starting $APP_NAME" - start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \ - --start --quiet \ - --pidfile $PID_PATH \ - --user $RUN_AS \ - --exec $DAEMON -- $DAEMON_OPTS + start ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 -esac \ No newline at end of file +esac
--- a/rhodecode/config/routing.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/config/routing.py Tue Apr 26 14:03:00 2011 +0200 @@ -105,16 +105,69 @@ controller='admin/repos_groups', path_prefix='/_admin') #ADMIN USER REST ROUTES - rmap.resource('user', 'users', controller='admin/users', - path_prefix='/_admin') + with rmap.submapper(path_prefix='/_admin', controller='admin/users') as m: + m.connect("users", "/users", + action="create", conditions=dict(method=["POST"])) + m.connect("users", "/users", + action="index", conditions=dict(method=["GET"])) + m.connect("formatted_users", "/users.{format}", + action="index", conditions=dict(method=["GET"])) + m.connect("new_user", "/users/new", + action="new", conditions=dict(method=["GET"])) + m.connect("formatted_new_user", "/users/new.{format}", + action="new", conditions=dict(method=["GET"])) + m.connect("update_user", "/users/{id}", + action="update", conditions=dict(method=["PUT"])) + m.connect("delete_user", "/users/{id}", + action="delete", conditions=dict(method=["DELETE"])) + m.connect("edit_user", "/users/{id}/edit", + action="edit", conditions=dict(method=["GET"])) + m.connect("formatted_edit_user", + "/users/{id}.{format}/edit", + action="edit", conditions=dict(method=["GET"])) + m.connect("user", "/users/{id}", + action="show", conditions=dict(method=["GET"])) + m.connect("formatted_user", "/users/{id}.{format}", + action="show", conditions=dict(method=["GET"])) + + #EXTRAS USER ROUTES + m.connect("user_perm", "/users_perm/{id}", + action="update_perm", conditions=dict(method=["PUT"])) #ADMIN USERS REST ROUTES - rmap.resource('users_group', 'users_groups', - controller='admin/users_groups', path_prefix='/_admin') + with rmap.submapper(path_prefix='/_admin', + controller='admin/users_groups') as m: + m.connect("users_groups", "/users_groups", + action="create", conditions=dict(method=["POST"])) + m.connect("users_groups", "/users_groups", + action="index", conditions=dict(method=["GET"])) + m.connect("formatted_users_groups", "/users_groups.{format}", + action="index", conditions=dict(method=["GET"])) + m.connect("new_users_group", "/users_groups/new", + action="new", conditions=dict(method=["GET"])) + m.connect("formatted_new_users_group", "/users_groups/new.{format}", + action="new", conditions=dict(method=["GET"])) + m.connect("update_users_group", "/users_groups/{id}", + action="update", conditions=dict(method=["PUT"])) + m.connect("delete_users_group", "/users_groups/{id}", + action="delete", conditions=dict(method=["DELETE"])) + m.connect("edit_users_group", "/users_groups/{id}/edit", + action="edit", conditions=dict(method=["GET"])) + m.connect("formatted_edit_users_group", + "/users_groups/{id}.{format}/edit", + action="edit", conditions=dict(method=["GET"])) + m.connect("users_group", "/users_groups/{id}", + action="show", conditions=dict(method=["GET"])) + m.connect("formatted_users_group", "/users_groups/{id}.{format}", + action="show", conditions=dict(method=["GET"])) + + #EXTRAS USER ROUTES + m.connect("users_group_perm", "/users_groups_perm/{id}", + action="update_perm", conditions=dict(method=["PUT"])) #ADMIN GROUP REST ROUTES - rmap.resource('group', 'groups', controller='admin/groups', - path_prefix='/_admin') + rmap.resource('group', 'groups', + controller='admin/groups', path_prefix='/_admin') #ADMIN PERMISSIONS REST ROUTES rmap.resource('permission', 'permissions', @@ -124,6 +177,7 @@ rmap.connect('ldap_settings', '/_admin/ldap', controller='admin/ldap_settings', action='ldap_settings', conditions=dict(method=["POST"])) + rmap.connect('ldap_home', '/_admin/ldap', controller='admin/ldap_settings') @@ -207,7 +261,9 @@ controller='feed', action='atom', conditions=dict(function=check_repo)) - #REPOSITORY ROUTES + #========================================================================== + # REPOSITORY ROUTES + #========================================================================== rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}', controller='changeset', revision='tip', conditions=dict(function=check_repo)) @@ -282,4 +338,7 @@ controller='settings', action='fork', conditions=dict(function=check_repo)) + rmap.connect('repo_followers_home', '/{repo_name:.*}/followers', + controller='followers', action='followers', + conditions=dict(function=check_repo)) return rmap
--- a/rhodecode/controllers/admin/permissions.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/controllers/admin/permissions.py Tue Apr 26 14:03:00 2011 +0200 @@ -33,7 +33,6 @@ from rhodecode.lib.base import BaseController, render from rhodecode.model.forms import LdapSettingsForm, DefaultPermissionsForm from rhodecode.model.permission import PermissionModel -from rhodecode.model.settings import SettingsModel from rhodecode.model.user import UserModel import formencode import logging
--- a/rhodecode/controllers/admin/users.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/controllers/admin/users.py Tue Apr 26 14:03:00 2011 +0200 @@ -38,7 +38,7 @@ from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator from rhodecode.lib.base import BaseController, render -from rhodecode.model.db import User +from rhodecode.model.db import User, RepoToPerm, UserToPerm, Permission from rhodecode.model.forms import UserForm from rhodecode.model.user import UserModel @@ -101,7 +101,7 @@ # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: - # h.form(url('user', id=ID), + # h.form(url('update_user', id=ID), # method='put') # url('user', id=ID) user_model = UserModel() @@ -113,13 +113,16 @@ try: form_result = _form.to_python(dict(request.POST)) user_model.update(id, form_result) - h.flash(_('User updated succesfully'), category='success') + h.flash(_('User updated successfully'), category='success') except formencode.Invalid, errors: + e = errors.error_dict or {} + perm = Permission.get_by_key('hg.create.repository') + e.update({'create_repo_perm': UserToPerm.has_perm(id, perm)}) return htmlfill.render( render('admin/users/user_edit.html'), defaults=errors.value, - errors=errors.error_dict or {}, + errors=e, prefix_error=False, encoding="UTF-8") except Exception: @@ -134,7 +137,7 @@ # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="DELETE" /> # Or using helpers: - # h.form(url('user', id=ID), + # h.form(url('delete_user', id=ID), # method='delete') # url('user', id=ID) user_model = UserModel() @@ -167,6 +170,8 @@ .permissions['global'] defaults = c.user.get_dict() + perm = Permission.get_by_key('hg.create.repository') + defaults.update({'create_repo_perm': UserToPerm.has_perm(id, perm)}) return htmlfill.render( render('admin/users/user_edit.html'), @@ -174,3 +179,29 @@ encoding="UTF-8", force_defaults=False ) + + def update_perm(self, id): + """PUT /users_perm/id: Update an existing item""" + # url('user_perm', id=ID, method='put') + + grant_perm = request.POST.get('create_repo_perm', False) + + if grant_perm: + perm = Permission.get_by_key('hg.create.none') + UserToPerm.revoke_perm(id, perm) + + perm = Permission.get_by_key('hg.create.repository') + UserToPerm.grant_perm(id, perm) + h.flash(_("Granted 'repository create' permission to user"), + category='success') + + else: + perm = Permission.get_by_key('hg.create.repository') + UserToPerm.revoke_perm(id, perm) + + perm = Permission.get_by_key('hg.create.none') + UserToPerm.grant_perm(id, perm) + h.flash(_("Revoked 'repository create' permission to user"), + category='success') + + return redirect(url('edit_user', id=id))
--- a/rhodecode/controllers/admin/users_groups.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/controllers/admin/users_groups.py Tue Apr 26 14:03:00 2011 +0200 @@ -36,9 +36,8 @@ from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator from rhodecode.lib.base import BaseController, render -from rhodecode.model.db import User, UsersGroup +from rhodecode.model.db import User, UsersGroup, Permission, UsersGroupToPerm from rhodecode.model.forms import UserForm, UsersGroupForm -from rhodecode.model.user import UserModel from rhodecode.model.users_group import UsersGroupModel log = logging.getLogger(__name__) @@ -123,10 +122,16 @@ category='success') #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa) except formencode.Invalid, errors: + e = errors.error_dict or {} + + perm = Permission.get_by_key('hg.create.repository') + e.update({'create_repo_perm': + UsersGroupToPerm.has_perm(id, perm)}) + return htmlfill.render( render('admin/users_groups/users_group_edit.html'), defaults=errors.value, - errors=errors.error_dict or {}, + errors=e, prefix_error=False, encoding="UTF-8") except Exception: @@ -171,10 +176,38 @@ c.available_members = [(x.user_id, x.username) for x in self.sa.query(User).all()] defaults = c.users_group.get_dict() - + perm = Permission.get_by_key('hg.create.repository') + defaults.update({'create_repo_perm': + UsersGroupToPerm.has_perm(id, perm)}) return htmlfill.render( render('admin/users_groups/users_group_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False ) + + def update_perm(self, id): + """PUT /users_perm/id: Update an existing item""" + # url('users_group_perm', id=ID, method='put') + + grant_perm = request.POST.get('create_repo_perm', False) + + if grant_perm: + perm = Permission.get_by_key('hg.create.none') + UsersGroupToPerm.revoke_perm(id, perm) + + perm = Permission.get_by_key('hg.create.repository') + UsersGroupToPerm.grant_perm(id, perm) + h.flash(_("Granted 'repository create' permission to user"), + category='success') + + else: + perm = Permission.get_by_key('hg.create.repository') + UsersGroupToPerm.revoke_perm(id, perm) + + perm = Permission.get_by_key('hg.create.none') + UsersGroupToPerm.grant_perm(id, perm) + h.flash(_("Revoked 'repository create' permission to user"), + category='success') + + return redirect(url('edit_users_group', id=id))
--- a/rhodecode/controllers/changelog.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/controllers/changelog.py Tue Apr 26 14:03:00 2011 +0200 @@ -84,7 +84,7 @@ :param size: number of commits to show :param p: page number """ - if not repo.revisions or repo.alias == 'git': + if not repo.revisions: c.jsdata = json.dumps([]) return @@ -93,12 +93,19 @@ rev_start = repo.revisions.index(repo.revisions[(-1 * offset)]) rev_end = max(0, rev_start - revcount) - dag = graph_rev(repo._repo, rev_start, rev_end) - c.dag = tree = list(colored(dag)) data = [] - for (id, type, ctx, vtx, edges) in tree: - if type != CHANGESET: - continue - data.append(('', vtx, edges)) + if repo.alias == 'git': + for _ in xrange(rev_end, rev_start): + vtx = [0, 1] + edges = [[0, 0, 1]] + data.append(['', vtx, edges]) + + elif repo.alias == 'hg': + dag = graph_rev(repo._repo, rev_start, rev_end) + c.dag = tree = list(colored(dag)) + for (id, type, ctx, vtx, edges) in tree: + if type != CHANGESET: + continue + data.append(['', vtx, edges]) c.jsdata = json.dumps(data)
--- a/rhodecode/controllers/changeset.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/controllers/changeset.py Tue Apr 26 14:03:00 2011 +0200 @@ -86,8 +86,11 @@ c.changes = OrderedDict() c.sum_added = 0 c.sum_removed = 0 - c.cut_off = False + c.lines_added = 0 + c.lines_deleted = 0 + c.cut_off = False # defines if cut off limit is reached + # Iterate over ranges (default changeset view is always one changeset) for changeset in c.cs_ranges: c.changes[changeset.raw_id] = [] try: @@ -99,15 +102,22 @@ # ADDED FILES #================================================================== for node in changeset.added: + filenode_old = FileNode(node.path, '', EmptyChangeset()) if filenode_old.is_binary or node.is_binary: diff = wrap_to_table(_('binary file')) + st = (0, 0) else: + # in this case node.size is good parameter since those are + # added nodes and their size defines how many changes were + # made c.sum_added += node.size if c.sum_added < self.cut_off_limit: f_gitdiff = differ.get_gitdiff(filenode_old, node) - diff = differ.DiffProcessor(f_gitdiff, - format='gitdiff').as_html() + d = differ.DiffProcessor(f_gitdiff, format='gitdiff') + + st = d.stat() + diff = d.as_html() else: diff = wrap_to_table(_('Changeset is to big and ' @@ -118,8 +128,10 @@ cs1 = None cs2 = node.last_changeset.raw_id - c.changes[changeset.raw_id].append(('added', node, - diff, cs1, cs2)) + c.lines_added += st[0] + c.lines_deleted += st[1] + c.changes[changeset.raw_id].append(('added', node, diff, + cs1, cs2, st)) #================================================================== # CHANGED FILES @@ -129,18 +141,27 @@ try: filenode_old = changeset_parent.get_node(node.path) except ChangesetError: + log.warning('Unable to fetch parent node for diff') filenode_old = FileNode(node.path, '', EmptyChangeset()) if filenode_old.is_binary or node.is_binary: diff = wrap_to_table(_('binary file')) + st = (0, 0) else: if c.sum_removed < self.cut_off_limit: f_gitdiff = differ.get_gitdiff(filenode_old, node) - diff = differ.DiffProcessor(f_gitdiff, - format='gitdiff')\ - .as_html() + d = differ.DiffProcessor(f_gitdiff, + format='gitdiff') + st = d.stat() + if (st[0] + st[1]) * 256 > self.cut_off_limit: + diff = wrap_to_table(_('Diff is to big ' + 'and was cut off, see ' + 'raw diff instead')) + else: + diff = d.as_html() + if diff: c.sum_removed += len(diff) else: @@ -152,8 +173,10 @@ cs1 = filenode_old.last_changeset.raw_id cs2 = node.last_changeset.raw_id - c.changes[changeset.raw_id].append(('changed', node, - diff, cs1, cs2)) + c.lines_added += st[0] + c.lines_deleted += st[1] + c.changes[changeset.raw_id].append(('changed', node, diff, + cs1, cs2, st)) #================================================================== # REMOVED FILES @@ -161,7 +184,7 @@ if not c.cut_off: for node in changeset.removed: c.changes[changeset.raw_id].append(('removed', node, None, - None, None)) + None, None, (0, 0))) if len(c.cs_ranges) == 1: c.changeset = c.cs_ranges[0]
--- a/rhodecode/controllers/files.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/controllers/files.py Tue Apr 26 14:03:00 2011 +0200 @@ -245,6 +245,7 @@ c.action = request.GET.get('diff') c.no_changes = diff1 == diff2 c.f_path = f_path + c.big_diff = False try: if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: @@ -286,7 +287,8 @@ c.cur_diff = _('Binary file') elif node1.size > self.cut_off_limit or \ node2.size > self.cut_off_limit: - c.cur_diff = _('Diff is too big to display') + c.cur_diff = '' + c.big_diff = True else: diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2), format='gitdiff') @@ -298,13 +300,15 @@ c.cur_diff = _('Binary file') elif node1.size > self.cut_off_limit or \ node2.size > self.cut_off_limit: - c.cur_diff = _('Diff is too big to display') + c.cur_diff = '' + c.big_diff = True + else: diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2), format='gitdiff') c.cur_diff = diff.as_html() - if not c.cur_diff: + if not c.cur_diff and not c.big_diff: c.no_changes = True return render('files/file_diff.html')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rhodecode/controllers/followers.py Tue Apr 26 14:03:00 2011 +0200 @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +""" + rhodecode.controllers.followers + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Followers controller for rhodecode + + :created_on: Apr 23, 2011 + :author: marcink + :copyright: (C) 2009-2011 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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, see <http://www.gnu.org/licenses/>. +import logging + +from pylons import tmpl_context as c, request + +from rhodecode.lib.helpers import Page +from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from rhodecode.lib.base import BaseRepoController, render +from rhodecode.model.db import Repository, User, UserFollowing + +log = logging.getLogger(__name__) + + +class FollowersController(BaseRepoController): + + @LoginRequired() + @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', + 'repository.admin') + def __before__(self): + super(FollowersController, self).__before__() + + def followers(self, repo_name): + p = int(request.params.get('page', 1)) + repo_id = getattr(Repository.by_repo_name(repo_name), 'repo_id') + d = UserFollowing.get_repo_followers(repo_id)\ + .order_by(UserFollowing.follows_from) + c.followers_pager = Page(d, page=p, items_per_page=20) + + c.followers_data = render('/followers/followers_data.html') + + if request.params.get('partial'): + return c.followers_data + + return render('/followers/followers.html')
--- a/rhodecode/controllers/summary.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/controllers/summary.py Tue Apr 26 14:03:00 2011 +0200 @@ -134,13 +134,13 @@ if stats and stats.languages: c.no_data = False is dbrepo.enable_statistics - lang_stats = json.loads(stats.languages) + lang_stats_d = json.loads(stats.languages) c.commit_data = stats.commit_activity c.overview_data = stats.commit_activity_combined lang_stats = [(x, {"count": y, "desc": LANGUAGES_EXTENSIONS_MAP.get(x)}) - for x, y in lang_stats.items()] + for x, y in lang_stats_d.items()] c.trending_languages = json.dumps(OrderedDict( sorted(lang_stats, reverse=True,
--- a/rhodecode/i18n/rhodecode.pot Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/i18n/rhodecode.pot Tue Apr 26 14:03:00 2011 +0200 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: RhodeCode 1.2.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2011-02-25 19:12+0100\n" +"POT-Creation-Date: 2011-04-21 00:05+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,361 +17,422 @@ "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.5\n" -#: rhodecode/controllers/changeset.py:104 rhodecode/controllers/changeset.py:129 -#: rhodecode/controllers/changeset.py:179 rhodecode/controllers/changeset.py:191 +#: rhodecode/controllers/changeset.py:106 rhodecode/controllers/changeset.py:141 +#: rhodecode/controllers/changeset.py:202 rhodecode/controllers/changeset.py:215 msgid "binary file" msgstr "" -#: rhodecode/controllers/changeset.py:112 rhodecode/controllers/changeset.py:138 +#: rhodecode/controllers/changeset.py:116 rhodecode/controllers/changeset.py:154 msgid "Changeset is to big and was cut off, see raw changeset instead" msgstr "" -#: rhodecode/controllers/error.py:71 +#: rhodecode/controllers/error.py:69 msgid "Home page" msgstr "" +#: rhodecode/controllers/error.py:98 +msgid "The request could not be understood by the server due to malformed syntax." +msgstr "" + #: rhodecode/controllers/error.py:101 -msgid "The request could not be understood by the server due to malformed syntax." +msgid "Unauthorized access to resource" msgstr "" #: rhodecode/controllers/error.py:103 -msgid "Unauthorized access to resource" +msgid "You don't have permission to view this page" msgstr "" #: rhodecode/controllers/error.py:105 -msgid "You don't have permission to view this page" +msgid "The resource could not be found" msgstr "" #: rhodecode/controllers/error.py:107 -msgid "The resource could not be found" -msgstr "" - -#: rhodecode/controllers/error.py:109 msgid "" "The server encountered an unexpected condition which prevented it from " "fulfilling the request." msgstr "" -#: rhodecode/controllers/feed.py:48 +#: rhodecode/controllers/feed.py:47 #, python-format msgid "Changes on %s repository" msgstr "" -#: rhodecode/controllers/files.py:67 rhodecode/controllers/files.py:120 +#: rhodecode/controllers/feed.py:48 +#, python-format +msgid "%s %s feed" +msgstr "" + +#: rhodecode/controllers/files.py:70 msgid "There are no files yet" msgstr "" -#: rhodecode/controllers/files.py:186 +#: rhodecode/controllers/files.py:225 msgid "downloads disabled" msgstr "" -#: rhodecode/controllers/files.py:191 +#: rhodecode/controllers/files.py:230 #, python-format msgid "Unknown revision %s" msgstr "" -#: rhodecode/controllers/files.py:193 +#: rhodecode/controllers/files.py:232 msgid "Empty repository" msgstr "" -#: rhodecode/controllers/files.py:195 +#: rhodecode/controllers/files.py:234 msgid "Unknown archive type" msgstr "" -#: rhodecode/controllers/files.py:248 rhodecode/controllers/files.py:257 -msgid "Diff is to big to display" -msgstr "" - -#: rhodecode/controllers/files.py:250 rhodecode/controllers/files.py:259 +#: rhodecode/controllers/files.py:286 rhodecode/controllers/files.py:298 msgid "Binary file" msgstr "" -#: rhodecode/controllers/files.py:272 +#: rhodecode/controllers/files.py:289 rhodecode/controllers/files.py:301 +msgid "Diff is too big to display" +msgstr "" + +#: rhodecode/controllers/files.py:315 +#: rhodecode/templates/changeset/changeset_range.html:4 +#: rhodecode/templates/changeset/changeset_range.html:12 +#: rhodecode/templates/changeset/changeset_range.html:29 msgid "Changesets" msgstr "" -#: rhodecode/controllers/files.py:273 rhodecode/controllers/summary.py:157 +#: rhodecode/controllers/files.py:316 rhodecode/controllers/summary.py:174 +#: rhodecode/templates/branches/branches.html:5 +#: rhodecode/templates/summary/summary.html:694 msgid "Branches" msgstr "" -#: rhodecode/controllers/files.py:274 rhodecode/controllers/summary.py:158 +#: rhodecode/controllers/files.py:317 rhodecode/controllers/summary.py:175 +#: rhodecode/templates/summary/summary.html:683 +#: rhodecode/templates/tags/tags.html:5 msgid "Tags" msgstr "" -#: rhodecode/controllers/login.py:112 +#: rhodecode/controllers/journal.py:50 +#, python-format +msgid "%s public journal %s feed" +msgstr "" + +#: rhodecode/controllers/journal.py:178 rhodecode/controllers/journal.py:212 +#: rhodecode/templates/admin/repos/repo_edit.html:357 +#: rhodecode/templates/base/base.html:14 +msgid "Public journal" +msgstr "" + +#: rhodecode/controllers/login.py:110 msgid "You have successfully registered into rhodecode" msgstr "" -#: rhodecode/controllers/login.py:134 +#: rhodecode/controllers/login.py:132 msgid "Your new password was sent" msgstr "" -#: rhodecode/controllers/search.py:110 +#: rhodecode/controllers/search.py:107 msgid "Invalid search query. Try quoting it." msgstr "" -#: rhodecode/controllers/search.py:115 +#: rhodecode/controllers/search.py:112 msgid "There is no index to search in. Please run whoosh indexer" msgstr "" -#: rhodecode/controllers/settings.py:62 rhodecode/controllers/settings.py:171 +#: rhodecode/controllers/settings.py:61 rhodecode/controllers/settings.py:170 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from the " "file system please run the application again in order to rescan repositories" msgstr "" -#: rhodecode/controllers/settings.py:109 rhodecode/controllers/admin/repos.py:146 +#: rhodecode/controllers/settings.py:109 rhodecode/controllers/admin/repos.py:235 #, python-format msgid "Repository %s updated successfully" msgstr "" -#: rhodecode/controllers/settings.py:126 rhodecode/controllers/admin/repos.py:187 +#: rhodecode/controllers/settings.py:126 rhodecode/controllers/admin/repos.py:253 #, python-format msgid "error occurred during update of repository %s" msgstr "" -#: rhodecode/controllers/settings.py:145 rhodecode/controllers/admin/repos.py:206 +#: rhodecode/controllers/settings.py:144 rhodecode/controllers/admin/repos.py:271 #, python-format msgid "" "%s repository is not mapped to db perhaps it was moved or renamed from the " "filesystem please run the application again in order to rescan repositories" msgstr "" -#: rhodecode/controllers/settings.py:157 rhodecode/controllers/admin/repos.py:218 +#: rhodecode/controllers/settings.py:156 rhodecode/controllers/admin/repos.py:283 #, python-format msgid "deleted repository %s" msgstr "" -#: rhodecode/controllers/settings.py:159 rhodecode/controllers/admin/repos.py:222 +#: rhodecode/controllers/settings.py:158 rhodecode/controllers/admin/repos.py:287 #, python-format msgid "An error occurred during deletion of %s" msgstr "" -#: rhodecode/controllers/settings.py:193 +#: rhodecode/controllers/settings.py:192 #, python-format msgid "forked %s repository as %s" msgstr "" -#: rhodecode/controllers/summary.py:117 +#: rhodecode/controllers/summary.py:122 msgid "No data loaded yet" msgstr "" -#: rhodecode/controllers/summary.py:120 +#: rhodecode/controllers/summary.py:125 msgid "Statistics are disabled for this repository" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:51 +#: rhodecode/controllers/admin/ldap_settings.py:48 msgid "BASE" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:52 +#: rhodecode/controllers/admin/ldap_settings.py:49 msgid "ONELEVEL" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:53 +#: rhodecode/controllers/admin/ldap_settings.py:50 msgid "SUBTREE" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:57 +#: rhodecode/controllers/admin/ldap_settings.py:54 msgid "NEVER" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:58 +#: rhodecode/controllers/admin/ldap_settings.py:55 msgid "ALLOW" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:59 +#: rhodecode/controllers/admin/ldap_settings.py:56 msgid "TRY" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:60 +#: rhodecode/controllers/admin/ldap_settings.py:57 msgid "DEMAND" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:61 +#: rhodecode/controllers/admin/ldap_settings.py:58 msgid "HARD" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:103 +#: rhodecode/controllers/admin/ldap_settings.py:100 msgid "Ldap settings updated successfully" msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:108 +#: rhodecode/controllers/admin/ldap_settings.py:105 msgid "Unable to activate ldap. The \"python-ldap\" library is missing." msgstr "" -#: rhodecode/controllers/admin/ldap_settings.py:124 +#: rhodecode/controllers/admin/ldap_settings.py:121 msgid "error occurred during update of ldap settings" msgstr "" +#: rhodecode/controllers/admin/permissions.py:57 +msgid "None" +msgstr "" + +#: rhodecode/controllers/admin/permissions.py:58 +msgid "Read" +msgstr "" + #: rhodecode/controllers/admin/permissions.py:59 -msgid "None" +msgid "Write" msgstr "" #: rhodecode/controllers/admin/permissions.py:60 -msgid "Read" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:61 -msgid "Write" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:62 +#: rhodecode/templates/admin/ldap/ldap.html:9 +#: rhodecode/templates/admin/permissions/permissions.html:9 +#: rhodecode/templates/admin/repos/repo_add.html:9 +#: rhodecode/templates/admin/repos/repo_edit.html:9 +#: rhodecode/templates/admin/repos/repos.html:10 +#: rhodecode/templates/admin/settings/settings.html:9 +#: rhodecode/templates/admin/users/user_add.html:8 +#: rhodecode/templates/admin/users/user_edit.html:9 +#: rhodecode/templates/admin/users/user_edit.html:110 +#: rhodecode/templates/admin/users/users.html:9 +#: rhodecode/templates/admin/users_groups/users_group_add.html:8 +#: rhodecode/templates/admin/users_groups/users_group_edit.html:9 +#: rhodecode/templates/admin/users_groups/users_groups.html:9 +#: rhodecode/templates/base/base.html:255 rhodecode/templates/base/base.html:344 +#: rhodecode/templates/base/base.html:346 rhodecode/templates/base/base.html:348 msgid "Admin" msgstr "" +#: rhodecode/controllers/admin/permissions.py:63 +msgid "disabled" +msgstr "" + #: rhodecode/controllers/admin/permissions.py:65 -msgid "disabled" +msgid "allowed with manual account activation" msgstr "" #: rhodecode/controllers/admin/permissions.py:67 -msgid "allowed with manual account activation" -msgstr "" - -#: rhodecode/controllers/admin/permissions.py:69 msgid "allowed with automatic account activation" msgstr "" -#: rhodecode/controllers/admin/permissions.py:71 +#: rhodecode/controllers/admin/permissions.py:69 msgid "Disabled" msgstr "" -#: rhodecode/controllers/admin/permissions.py:72 +#: rhodecode/controllers/admin/permissions.py:70 msgid "Enabled" msgstr "" -#: rhodecode/controllers/admin/permissions.py:106 +#: rhodecode/controllers/admin/permissions.py:103 msgid "Default permissions updated successfully" msgstr "" -#: rhodecode/controllers/admin/permissions.py:123 +#: rhodecode/controllers/admin/permissions.py:120 msgid "error occurred during update of permissions" msgstr "" -#: rhodecode/controllers/admin/repos.py:86 -#, python-format -msgid "created repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:113 -#, python-format -msgid "error occurred during creation of repository %s" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:239 -msgid "An error occurred during deletion of repository user" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:254 -msgid "An error occurred during deletion of repository users groups" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:271 -msgid "An error occurred during deletion of repository stats" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:286 -msgid "An error occurred during cache invalidation" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:306 -msgid "Updated repository visibility in public journal" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:309 -msgid "An error occurred during setting this repository in public journal" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:314 rhodecode/model/forms.py:54 -msgid "Token mismatch" -msgstr "" - -#: rhodecode/controllers/admin/repos.py:334 +#: rhodecode/controllers/admin/repos.py:95 #, python-format msgid "" "%s repository is not mapped to db perhaps it was created or renamed from the " "filesystem please run the application again in order to rescan repositories" msgstr "" -#: rhodecode/controllers/admin/settings.py:113 +#: rhodecode/controllers/admin/repos.py:169 +#, python-format +msgid "created repository %s from %s" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:173 +#, python-format +msgid "created repository %s" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:201 +#, python-format +msgid "error occurred during creation of repository %s" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:304 +msgid "An error occurred during deletion of repository user" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:319 +msgid "An error occurred during deletion of repository users groups" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:336 +msgid "An error occurred during deletion of repository stats" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:351 +msgid "An error occurred during cache invalidation" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:371 +msgid "Updated repository visibility in public journal" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:374 +msgid "An error occurred during setting this repository in public journal" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:379 rhodecode/model/forms.py:53 +msgid "Token mismatch" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:392 +msgid "Pulled from remote location" +msgstr "" + +#: rhodecode/controllers/admin/repos.py:394 +msgid "An error occurred during pull from remote location" +msgstr "" + +#: rhodecode/controllers/admin/settings.py:109 #, python-format msgid "Repositories successfully rescanned added: %s,removed: %s" msgstr "" -#: rhodecode/controllers/admin/settings.py:122 +#: rhodecode/controllers/admin/settings.py:118 msgid "Whoosh reindex task scheduled" msgstr "" -#: rhodecode/controllers/admin/settings.py:147 +#: rhodecode/controllers/admin/settings.py:144 msgid "Updated application settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:152 -#: rhodecode/controllers/admin/settings.py:213 +#: rhodecode/controllers/admin/settings.py:149 +#: rhodecode/controllers/admin/settings.py:216 msgid "error occurred during updating application settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:208 +#: rhodecode/controllers/admin/settings.py:211 msgid "Updated mercurial settings" msgstr "" -#: rhodecode/controllers/admin/settings.py:265 +#: rhodecode/controllers/admin/settings.py:268 msgid "You can't edit this user since it's crucial for entire application" msgstr "" -#: rhodecode/controllers/admin/settings.py:293 +#: rhodecode/controllers/admin/settings.py:297 msgid "Your account was updated successfully" msgstr "" -#: rhodecode/controllers/admin/settings.py:313 -#: rhodecode/controllers/admin/users.py:128 +#: rhodecode/controllers/admin/settings.py:317 +#: rhodecode/controllers/admin/users.py:130 #, python-format msgid "error occurred during update of user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:79 +#: rhodecode/controllers/admin/users.py:78 #, python-format msgid "created user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:91 +#: rhodecode/controllers/admin/users.py:90 #, python-format msgid "error occurred during creation of user %s" msgstr "" -#: rhodecode/controllers/admin/users.py:117 -msgid "User updated succesfully" +#: rhodecode/controllers/admin/users.py:116 +msgid "User updated successfully" msgstr "" -#: rhodecode/controllers/admin/users.py:144 +#: rhodecode/controllers/admin/users.py:146 msgid "successfully deleted user" msgstr "" -#: rhodecode/controllers/admin/users.py:148 +#: rhodecode/controllers/admin/users.py:150 msgid "An error occurred during deletion of user" msgstr "" -#: rhodecode/controllers/admin/users.py:164 +#: rhodecode/controllers/admin/users.py:166 msgid "You can't edit this user" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:78 +#: rhodecode/controllers/admin/users.py:195 +#: rhodecode/controllers/admin/users_groups.py:201 +msgid "Granted 'repository create' permission to user" +msgstr "" + +#: rhodecode/controllers/admin/users.py:204 +#: rhodecode/controllers/admin/users_groups.py:210 +msgid "Revoked 'repository create' permission to user" +msgstr "" + +#: rhodecode/controllers/admin/users_groups.py:74 #, python-format msgid "created users group %s" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:90 +#: rhodecode/controllers/admin/users_groups.py:86 #, python-format msgid "error occurred during creation of users group %s" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:125 +#: rhodecode/controllers/admin/users_groups.py:120 #, python-format msgid "updated users group %s" msgstr "" -#: rhodecode/controllers/admin/users_groups.py:137 +#: rhodecode/controllers/admin/users_groups.py:139 #, python-format msgid "error occurred during update of users group %s" msgstr "" @@ -384,218 +445,1651 @@ msgid "An error occurred during deletion of users group" msgstr "" -#: rhodecode/lib/auth.py:390 +#: rhodecode/lib/auth.py:380 msgid "You need to be a registered user to perform this action" msgstr "" -#: rhodecode/lib/helpers.py:394 +#: rhodecode/lib/helpers.py:343 msgid "ago" msgstr "" -#: rhodecode/lib/helpers.py:397 +#: rhodecode/lib/helpers.py:346 msgid "just now" msgstr "" -#: rhodecode/lib/helpers.py:416 +#: rhodecode/lib/helpers.py:365 msgid "True" msgstr "" -#: rhodecode/lib/helpers.py:420 +#: rhodecode/lib/helpers.py:369 msgid "False" msgstr "" -#: rhodecode/lib/helpers.py:461 +#: rhodecode/lib/helpers.py:411 #, python-format msgid "Show all combined changesets %s->%s" msgstr "" -#: rhodecode/lib/helpers.py:465 +#: rhodecode/lib/helpers.py:415 msgid "compare view" msgstr "" -#: rhodecode/lib/helpers.py:473 +#: rhodecode/lib/helpers.py:424 msgid "and" msgstr "" -#: rhodecode/lib/helpers.py:473 +#: rhodecode/lib/helpers.py:424 #, python-format msgid "%s more" msgstr "" -#: rhodecode/lib/helpers.py:475 +#: rhodecode/lib/helpers.py:426 rhodecode/templates/changelog/changelog.html:14 +#: rhodecode/templates/changelog/changelog.html:39 msgid "revisions" msgstr "" -#: rhodecode/lib/helpers.py:489 +#: rhodecode/lib/helpers.py:444 msgid "fork name " msgstr "" -#: rhodecode/lib/helpers.py:492 +#: rhodecode/lib/helpers.py:447 msgid "[deleted] repository" msgstr "" -#: rhodecode/lib/helpers.py:493 rhodecode/lib/helpers.py:497 +#: rhodecode/lib/helpers.py:448 rhodecode/lib/helpers.py:452 msgid "[created] repository" msgstr "" -#: rhodecode/lib/helpers.py:494 rhodecode/lib/helpers.py:498 +#: rhodecode/lib/helpers.py:449 rhodecode/lib/helpers.py:453 msgid "[forked] repository" msgstr "" -#: rhodecode/lib/helpers.py:495 rhodecode/lib/helpers.py:499 +#: rhodecode/lib/helpers.py:450 rhodecode/lib/helpers.py:454 msgid "[updated] repository" msgstr "" -#: rhodecode/lib/helpers.py:496 +#: rhodecode/lib/helpers.py:451 msgid "[delete] repository" msgstr "" -#: rhodecode/lib/helpers.py:500 +#: rhodecode/lib/helpers.py:455 msgid "[pushed] into" msgstr "" -#: rhodecode/lib/helpers.py:501 +#: rhodecode/lib/helpers.py:456 +msgid "[pulled from remote] into" +msgstr "" + +#: rhodecode/lib/helpers.py:457 msgid "[pulled] from" msgstr "" -#: rhodecode/lib/helpers.py:502 +#: rhodecode/lib/helpers.py:458 msgid "[started following] repository" msgstr "" -#: rhodecode/lib/helpers.py:503 +#: rhodecode/lib/helpers.py:459 msgid "[stopped following] repository" msgstr "" -#: rhodecode/lib/helpers.py:590 +#: rhodecode/lib/helpers.py:624 #, python-format msgid " and %s more" msgstr "" -#: rhodecode/lib/helpers.py:593 +#: rhodecode/lib/helpers.py:628 msgid "No Files" msgstr "" -#: rhodecode/model/forms.py:67 +#: rhodecode/model/forms.py:66 msgid "Invalid username" msgstr "" -#: rhodecode/model/forms.py:76 +#: rhodecode/model/forms.py:75 msgid "This username already exists" msgstr "" -#: rhodecode/model/forms.py:81 +#: rhodecode/model/forms.py:79 msgid "" "Username may only contain alphanumeric characters underscores, periods or " "dashes and must begin with alphanumeric character" msgstr "" -#: rhodecode/model/forms.py:99 +#: rhodecode/model/forms.py:94 msgid "Invalid group name" msgstr "" -#: rhodecode/model/forms.py:109 +#: rhodecode/model/forms.py:104 msgid "This users group already exists" msgstr "" -#: rhodecode/model/forms.py:114 +#: rhodecode/model/forms.py:110 msgid "" "Group name may only contain alphanumeric characters underscores, periods or " "dashes and must begin with alphanumeric character" msgstr "" -#: rhodecode/model/forms.py:134 rhodecode/model/forms.py:142 -#: rhodecode/model/forms.py:150 +#: rhodecode/model/forms.py:130 rhodecode/model/forms.py:138 +#: rhodecode/model/forms.py:146 msgid "Invalid characters in password" msgstr "" -#: rhodecode/model/forms.py:161 +#: rhodecode/model/forms.py:157 msgid "Password do not match" msgstr "" -#: rhodecode/model/forms.py:166 +#: rhodecode/model/forms.py:162 msgid "invalid password" msgstr "" -#: rhodecode/model/forms.py:167 +#: rhodecode/model/forms.py:163 msgid "invalid user name" msgstr "" -#: rhodecode/model/forms.py:168 +#: rhodecode/model/forms.py:164 msgid "Your account is disabled" msgstr "" -#: rhodecode/model/forms.py:205 +#: rhodecode/model/forms.py:201 msgid "This username is not valid" msgstr "" +#: rhodecode/model/forms.py:214 +msgid "This repository name is disallowed" +msgstr "" + #: rhodecode/model/forms.py:218 -msgid "This repository name is disallowed" -msgstr "" - -#: rhodecode/model/forms.py:222 msgid "This repository already exists" msgstr "" -#: rhodecode/model/forms.py:234 +#: rhodecode/model/forms.py:237 rhodecode/model/forms.py:243 +msgid "invalid clone url" +msgstr "" + +#: rhodecode/model/forms.py:246 +msgid "Invalid clone url, provide a valid clone http\\s url" +msgstr "" + +#: rhodecode/model/forms.py:257 msgid "Fork have to be the same type as original" msgstr "" -#: rhodecode/model/forms.py:240 +#: rhodecode/model/forms.py:263 msgid "This username or users group name is not valid" msgstr "" -#: rhodecode/model/forms.py:303 +#: rhodecode/model/forms.py:326 msgid "This is not a valid path" msgstr "" -#: rhodecode/model/forms.py:317 +#: rhodecode/model/forms.py:340 msgid "This e-mail address is already taken" msgstr "" -#: rhodecode/model/forms.py:333 +#: rhodecode/model/forms.py:356 msgid "This e-mail address doesn't exist." msgstr "" -#: rhodecode/model/forms.py:355 +#: rhodecode/model/forms.py:378 msgid "" "The LDAP Login attribute of the CN must be specified - this is the name of " "the attribute that is equivalent to 'username'" msgstr "" -#: rhodecode/model/forms.py:374 +#: rhodecode/model/forms.py:397 msgid "Please enter a login" msgstr "" -#: rhodecode/model/forms.py:375 +#: rhodecode/model/forms.py:398 #, python-format msgid "Enter a value %(min)i characters long or more" msgstr "" -#: rhodecode/model/forms.py:383 +#: rhodecode/model/forms.py:406 msgid "Please enter a password" msgstr "" -#: rhodecode/model/forms.py:384 +#: rhodecode/model/forms.py:407 #, python-format msgid "Enter %(min)i characters or more" msgstr "" -#: rhodecode/model/user.py:128 +#: rhodecode/model/user.py:145 msgid "[RhodeCode] New User registration" msgstr "" -#: rhodecode/model/user.py:140 rhodecode/model/user.py:161 +#: rhodecode/model/user.py:157 rhodecode/model/user.py:179 msgid "You can't Edit this user since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:182 +#: rhodecode/model/user.py:201 msgid "You can't remove this user since it's crucial for entire application" msgstr "" -#: rhodecode/model/user.py:185 +#: rhodecode/model/user.py:204 #, python-format msgid "" "This user still owns %s repositories and cannot be removed. Switch owners or " "remove those repositories" msgstr "" +#: rhodecode/templates/index.html:4 rhodecode/templates/index.html:35 +msgid "Dashboard" +msgstr "" + +#: rhodecode/templates/index.html:33 +#: rhodecode/templates/admin/users/user_edit_my_account.html:102 +msgid "quick filter..." +msgstr "" + +#: rhodecode/templates/index.html:35 rhodecode/templates/base/base.html:276 +msgid "repositories" +msgstr "" + +#: rhodecode/templates/index.html:41 +msgid "ADD NEW REPOSITORY" +msgstr "" + +#: rhodecode/templates/index.html:52 +#: rhodecode/templates/admin/repos/repo_add_base.html:9 +#: rhodecode/templates/admin/repos/repo_edit.html:32 +#: rhodecode/templates/admin/repos/repos.html:30 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:39 +#: rhodecode/templates/admin/users/user_edit_my_account.html:117 +#: rhodecode/templates/files/files_browser.html:44 +#: rhodecode/templates/settings/repo_settings.html:31 +#: rhodecode/templates/summary/summary.html:31 +#: rhodecode/templates/summary/summary.html:109 +msgid "Name" +msgstr "" + +#: rhodecode/templates/index.html:53 +#: rhodecode/templates/admin/repos/repo_add_base.html:42 +#: rhodecode/templates/admin/repos/repo_edit.html:65 +#: rhodecode/templates/admin/repos/repos.html:31 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:40 +#: rhodecode/templates/settings/repo_fork.html:40 +#: rhodecode/templates/settings/repo_settings.html:40 +#: rhodecode/templates/summary/summary.html:92 +msgid "Description" +msgstr "" + +#: rhodecode/templates/index.html:54 rhodecode/templates/admin/repos/repos.html:32 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:41 +#: rhodecode/templates/summary/summary.html:116 +msgid "Last change" +msgstr "" + +#: rhodecode/templates/index.html:55 rhodecode/templates/admin/repos/repos.html:33 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:42 +msgid "Tip" +msgstr "" + +#: rhodecode/templates/index.html:56 +#: rhodecode/templates/admin/repos/repo_edit.html:98 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:43 +msgid "Owner" +msgstr "" + +#: rhodecode/templates/index.html:57 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:44 +#: rhodecode/templates/journal/public_journal.html:20 +#: rhodecode/templates/summary/summary.html:179 +#: rhodecode/templates/summary/summary.html:182 +msgid "RSS" +msgstr "" + +#: rhodecode/templates/index.html:58 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:45 +#: rhodecode/templates/journal/public_journal.html:23 +#: rhodecode/templates/summary/summary.html:180 +#: rhodecode/templates/summary/summary.html:183 +msgid "Atom" +msgstr "" + +#: rhodecode/templates/index.html:68 rhodecode/templates/admin/repos/repos.html:42 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:55 +#: rhodecode/templates/admin/users/user_edit_my_account.html:127 +#: rhodecode/templates/summary/summary.html:48 +msgid "Mercurial repository" +msgstr "" + +#: rhodecode/templates/index.html:70 rhodecode/templates/admin/repos/repos.html:44 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:57 +#: rhodecode/templates/admin/users/user_edit_my_account.html:129 +#: rhodecode/templates/summary/summary.html:51 +msgid "Git repository" +msgstr "" + +#: rhodecode/templates/index.html:77 +#: rhodecode/templates/admin/repos/repo_edit_perms.html:27 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:64 +#: rhodecode/templates/journal/journal.html:53 +#: rhodecode/templates/summary/summary.html:56 +msgid "private repository" +msgstr "" + +#: rhodecode/templates/index.html:79 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:66 +#: rhodecode/templates/journal/journal.html:55 +#: rhodecode/templates/summary/summary.html:58 +msgid "public repository" +msgstr "" + +#: rhodecode/templates/index.html:87 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:74 +#: rhodecode/templates/base/base.html:267 +#: rhodecode/templates/settings/repo_fork.html:13 +msgid "fork" +msgstr "" + +#: rhodecode/templates/index.html:88 rhodecode/templates/admin/repos/repos.html:60 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:75 +#: rhodecode/templates/admin/users/user_edit_my_account.html:143 +#: rhodecode/templates/summary/summary.html:69 +#: rhodecode/templates/summary/summary.html:71 +msgid "Fork of" +msgstr "" + +#: rhodecode/templates/index.html:109 rhodecode/templates/admin/repos/repos.html:73 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:96 +msgid "No changesets yet" +msgstr "" + +#: rhodecode/templates/index.html:115 rhodecode/templates/index.html:117 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:102 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:104 +#, python-format +msgid "Subscribe to %s rss feed" +msgstr "" + +#: rhodecode/templates/index.html:122 rhodecode/templates/index.html:124 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:109 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:111 +#, python-format +msgid "Subscribe to %s atom feed" +msgstr "" + +#: rhodecode/templates/login.html:5 +msgid "Sign In" +msgstr "" + +#: rhodecode/templates/login.html:21 +msgid "Sign In to" +msgstr "" + +#: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20 +#: rhodecode/templates/admin/admin_log.html:5 +#: rhodecode/templates/admin/users/user_add.html:32 +#: rhodecode/templates/admin/users/user_edit.html:47 +#: rhodecode/templates/admin/users/user_edit_my_account.html:45 +#: rhodecode/templates/summary/summary.html:108 +msgid "Username" +msgstr "" + +#: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29 +#: rhodecode/templates/admin/ldap/ldap.html:46 +#: rhodecode/templates/admin/users/user_add.html:41 +msgid "Password" +msgstr "" + +#: rhodecode/templates/login.html:60 +msgid "Forgot your password ?" +msgstr "" + +#: rhodecode/templates/login.html:63 +msgid "Don't have an account ?" +msgstr "" + +#: rhodecode/templates/password_reset.html:5 +msgid "Reset You password" +msgstr "" + +#: rhodecode/templates/password_reset.html:11 +msgid "Reset You password to" +msgstr "" + +#: rhodecode/templates/password_reset.html:21 +msgid "Email address" +msgstr "" + +#: rhodecode/templates/password_reset.html:31 +msgid "Your new password will be send to matching email address" +msgstr "" + +#: rhodecode/templates/register.html:5 +msgid "Sign Up" +msgstr "" + +#: rhodecode/templates/register.html:11 +msgid "Sign Up to" +msgstr "" + +#: rhodecode/templates/register.html:38 +msgid "Re-enter password" +msgstr "" + +#: rhodecode/templates/register.html:47 +#: rhodecode/templates/admin/users/user_add.html:50 +#: rhodecode/templates/admin/users/user_edit.html:74 +#: rhodecode/templates/admin/users/user_edit_my_account.html:63 +msgid "First Name" +msgstr "" + +#: rhodecode/templates/register.html:56 +#: rhodecode/templates/admin/users/user_add.html:59 +#: rhodecode/templates/admin/users/user_edit.html:83 +#: rhodecode/templates/admin/users/user_edit_my_account.html:72 +msgid "Last Name" +msgstr "" + +#: rhodecode/templates/register.html:65 +#: rhodecode/templates/admin/users/user_add.html:68 +#: rhodecode/templates/admin/users/user_edit.html:92 +#: rhodecode/templates/admin/users/user_edit_my_account.html:81 +#: rhodecode/templates/summary/summary.html:110 +msgid "Email" +msgstr "" + +#: rhodecode/templates/register.html:76 +msgid "Your account will be activated right after registration" +msgstr "" + +#: rhodecode/templates/register.html:78 +msgid "Your account must wait for activation by administrator" +msgstr "" + +#: rhodecode/templates/repo_switcher_list.html:14 +msgid "Private repository" +msgstr "" + +#: rhodecode/templates/repo_switcher_list.html:19 +msgid "Public repository" +msgstr "" + +#: rhodecode/templates/admin/admin.html:5 rhodecode/templates/admin/admin.html:9 +msgid "Admin journal" +msgstr "" + +#: rhodecode/templates/admin/admin_log.html:6 +msgid "Action" +msgstr "" + +#: rhodecode/templates/admin/admin_log.html:7 +msgid "Repository" +msgstr "" + +#: rhodecode/templates/admin/admin_log.html:8 +msgid "Date" +msgstr "" + +#: rhodecode/templates/admin/admin_log.html:9 +msgid "From IP" +msgstr "" + +#: rhodecode/templates/admin/admin_log.html:61 +msgid "No actions yet" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:5 +msgid "LDAP administration" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:11 +msgid "Ldap" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:28 +msgid "Connection settings" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:30 +msgid "Enable LDAP" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:34 +msgid "Host" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:38 +msgid "Port" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:42 +msgid "Account" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:50 +msgid "Enable LDAPS" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:54 +msgid "Certificate Checks" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:57 +msgid "Search settings" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:59 +msgid "Base DN" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:63 +msgid "LDAP Filter" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:67 +msgid "LDAP Search Scope" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:70 +msgid "Attribute mappings" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:72 +msgid "Login Attribute" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:76 +msgid "First Name Attribute" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:80 +msgid "Last Name Attribute" +msgstr "" + +#: rhodecode/templates/admin/ldap/ldap.html:84 +msgid "E-mail Attribute" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:5 +msgid "Permissions administration" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:11 +#: rhodecode/templates/admin/repos/repo_edit.html:110 +#: rhodecode/templates/admin/users/user_edit.html:127 +#: rhodecode/templates/admin/users_groups/users_group_edit.html:248 +#: rhodecode/templates/settings/repo_settings.html:58 +msgid "Permissions" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:24 +msgid "Default permissions" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:31 +msgid "Anonymous access" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:41 +msgid "Repository permission" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:49 +msgid "" +"All default permissions on each repository will be reset to choosen " +"permission, note that all custom default permission on repositories will be " +"lost" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:50 +msgid "overwrite existing settings" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:55 +msgid "Registration" +msgstr "" + +#: rhodecode/templates/admin/permissions/permissions.html:63 +msgid "Repository creation" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add.html:5 +#: rhodecode/templates/admin/repos/repo_add_create_repository.html:5 +msgid "Add repository" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add.html:11 +#: rhodecode/templates/admin/repos/repo_edit.html:11 +#: rhodecode/templates/admin/repos/repos.html:10 +msgid "Repositories" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add.html:13 +msgid "add new" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add_base.html:17 +#: rhodecode/templates/summary/summary.html:80 +#: rhodecode/templates/summary/summary.html:82 +msgid "Clone from" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add_base.html:25 +#: rhodecode/templates/admin/repos/repo_edit.html:48 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:5 +msgid "Repository group" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add_base.html:29 +#: rhodecode/templates/admin/repos/repo_edit.html:52 +msgid "add new group" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add_base.html:34 +#: rhodecode/templates/admin/repos/repo_edit.html:57 +msgid "Type" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add_base.html:50 +#: rhodecode/templates/admin/repos/repo_edit.html:74 +#: rhodecode/templates/settings/repo_fork.html:48 +#: rhodecode/templates/settings/repo_settings.html:49 +msgid "Private" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_add_create_repository.html:9 +msgid "add new repository" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:5 +msgid "Edit repository" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:13 +#: rhodecode/templates/admin/users/user_edit.html:13 +#: rhodecode/templates/admin/users/user_edit_my_account.html:148 +#: rhodecode/templates/admin/users_groups/users_group_edit.html:13 +msgid "edit" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:40 +msgid "Clone uri" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:82 +msgid "Enable statistics" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:90 +msgid "Enable downloads" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:227 +#: rhodecode/templates/admin/repos_groups/repos_groups.html:10 +msgid "Group" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:228 +#: rhodecode/templates/admin/users_groups/users_groups.html:33 +msgid "members" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:313 +msgid "Administration" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:316 +msgid "Statistics" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:320 +msgid "Reset current statistics" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:323 +msgid "Fetched to rev" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:324 +msgid "Percentage of stats gathered" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:333 +msgid "Remote" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:337 +msgid "Pull changes from remote location" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:348 +msgid "Cache" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:352 +msgid "Invalidate repository cache" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:363 +msgid "Remove from public journal" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:365 +msgid "Add to public journal" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:371 +msgid "Delete" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit.html:375 +msgid "Remove this repository" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_perms.html:3 +msgid "none" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_perms.html:4 +msgid "read" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_perms.html:5 +msgid "write" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_perms.html:6 +#: rhodecode/templates/admin/users/users.html:38 +#: rhodecode/templates/base/base.html:272 +msgid "admin" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_perms.html:7 +msgid "member" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_perms.html:18 +msgid "Failed to remove user" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_perms.html:57 +msgid "Failed to remove users group" +msgstr "" + +#: rhodecode/templates/admin/repos/repo_edit_perms.html:91 +msgid "Add another member" +msgstr "" + +#: rhodecode/templates/admin/repos/repos.html:5 +msgid "Repositories administration" +msgstr "" + +#: rhodecode/templates/admin/repos/repos.html:34 +#: rhodecode/templates/summary/summary.html:102 +msgid "Contact" +msgstr "" + +#: rhodecode/templates/admin/repos/repos.html:35 +#: rhodecode/templates/admin/users/user_edit_my_account.html:119 +#: rhodecode/templates/admin/users/users.html:40 +#: rhodecode/templates/admin/users_groups/users_groups.html:35 +msgid "action" +msgstr "" + +#: rhodecode/templates/admin/repos/repos.html:51 +#: rhodecode/templates/admin/users/user_edit_my_account.html:134 +#: rhodecode/templates/admin/users/user_edit_my_account.html:148 +msgid "private" +msgstr "" + +#: rhodecode/templates/admin/repos/repos.html:53 +#: rhodecode/templates/admin/repos/repos.html:59 +#: rhodecode/templates/admin/users/user_edit_my_account.html:136 +#: rhodecode/templates/admin/users/user_edit_my_account.html:142 +#: rhodecode/templates/summary/summary.html:68 +msgid "public" +msgstr "" + +#: rhodecode/templates/admin/repos_groups/repos_groups.html:10 +#, python-format +msgid " %s repositories" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:5 +msgid "Settings administration" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:9 +#: rhodecode/templates/settings/repo_settings.html:5 +#: rhodecode/templates/settings/repo_settings.html:13 +msgid "Settings" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:24 +msgid "Remap and rescan repositories" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:32 +msgid "rescan option" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:38 +msgid "" +"In case a repository was deleted from filesystem and there are leftovers in " +"the database check this option to scan obsolete data in database and remove " +"it." +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:39 +msgid "destroy old data" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:51 +msgid "Whoosh indexing" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:59 +msgid "index build option" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:64 +msgid "build from scratch" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:76 +msgid "Global application settings" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:85 +msgid "Application name" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:94 +msgid "Realm text" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:103 +msgid "GA code" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:118 +msgid "Mercurial settings" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:127 +msgid "Web" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:132 +msgid "require ssl for pushing" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:139 +msgid "Hooks" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:144 +msgid "Update repository after push (hg update)" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:148 +msgid "Show repository size after push" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:152 +msgid "Log user push commands" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:156 +msgid "Log user pull commands" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:163 +msgid "Repositories location" +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:168 +msgid "" +"This a crucial application setting. If You really sure you need to change " +"this, you must restart application in order to make this settings take " +"effect. Click this label to unlock." +msgstr "" + +#: rhodecode/templates/admin/settings/settings.html:169 +msgid "unlock" +msgstr "" + +#: rhodecode/templates/admin/users/user_add.html:5 +msgid "Add user" +msgstr "" + +#: rhodecode/templates/admin/users/user_add.html:10 +#: rhodecode/templates/admin/users/user_edit.html:11 +#: rhodecode/templates/admin/users/users.html:9 +msgid "Users" +msgstr "" + +#: rhodecode/templates/admin/users/user_add.html:12 +msgid "add new user" +msgstr "" + +#: rhodecode/templates/admin/users/user_add.html:77 +#: rhodecode/templates/admin/users/user_edit.html:101 +#: rhodecode/templates/admin/users_groups/users_group_add.html:41 +#: rhodecode/templates/admin/users_groups/users_group_edit.html:42 +msgid "Active" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit.html:5 +msgid "Edit user" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit.html:34 +#: rhodecode/templates/admin/users/user_edit_my_account.html:33 +msgid "Using" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit.html:40 +#: rhodecode/templates/admin/users/user_edit_my_account.html:39 +msgid "API key" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit.html:56 +msgid "LDAP DN" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit.html:65 +#: rhodecode/templates/admin/users/user_edit_my_account.html:54 +msgid "New password" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit.html:135 +#: rhodecode/templates/admin/users_groups/users_group_edit.html:256 +msgid "Create repositories" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit_my_account.html:5 +msgid "My account" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit_my_account.html:9 +msgid "My Account" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit_my_account.html:101 +msgid "My repositories" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit_my_account.html:107 +msgid "ADD REPOSITORY" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit_my_account.html:118 +#: rhodecode/templates/branches/branches_data.html:7 +#: rhodecode/templates/shortlog/shortlog_data.html:8 +#: rhodecode/templates/tags/tags_data.html:7 +msgid "revision" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit_my_account.html:157 +msgid "No repositories yet" +msgstr "" + +#: rhodecode/templates/admin/users/user_edit_my_account.html:159 +msgid "create one now" +msgstr "" + +#: rhodecode/templates/admin/users/users.html:5 +msgid "Users administration" +msgstr "" + +#: rhodecode/templates/admin/users/users.html:33 +msgid "username" +msgstr "" + +#: rhodecode/templates/admin/users/users.html:34 +#: rhodecode/templates/branches/branches_data.html:5 +#: rhodecode/templates/tags/tags_data.html:5 +msgid "name" +msgstr "" + +#: rhodecode/templates/admin/users/users.html:35 +msgid "lastname" +msgstr "" + +#: rhodecode/templates/admin/users/users.html:36 +msgid "last login" +msgstr "" + +#: rhodecode/templates/admin/users/users.html:37 +#: rhodecode/templates/admin/users_groups/users_groups.html:34 +msgid "active" +msgstr "" + +#: rhodecode/templates/admin/users/users.html:39 +#: rhodecode/templates/base/base.html:280 +msgid "ldap" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_add.html:5 +msgid "Add users group" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_add.html:10 +#: rhodecode/templates/admin/users_groups/users_groups.html:9 +msgid "Users groups" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_add.html:12 +msgid "add new users group" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_add.html:32 +#: rhodecode/templates/admin/users_groups/users_group_edit.html:33 +msgid "Group name" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_edit.html:5 +msgid "Edit users group" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_edit.html:11 +msgid "UsersGroups" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_edit.html:50 +msgid "Members" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_edit.html:58 +msgid "Choosen group members" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_edit.html:61 +msgid "Remove all elements" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_edit.html:75 +msgid "Available members" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_group_edit.html:79 +msgid "Add all elements" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_groups.html:5 +msgid "Users groups administration" +msgstr "" + +#: rhodecode/templates/admin/users_groups/users_groups.html:32 +msgid "group name" +msgstr "" + +#: rhodecode/templates/base/base.html:21 rhodecode/templates/base/base.html:316 +#: rhodecode/templates/base/base.html:318 rhodecode/templates/base/base.html:320 +msgid "Home" +msgstr "" + +#: rhodecode/templates/base/base.html:25 rhodecode/templates/base/base.html:325 +#: rhodecode/templates/base/base.html:327 rhodecode/templates/base/base.html:329 +#: rhodecode/templates/journal/journal.html:4 +#: rhodecode/templates/journal/journal.html:17 +#: rhodecode/templates/journal/public_journal.html:4 +msgid "Journal" +msgstr "" + +#: rhodecode/templates/base/base.html:71 +msgid "Submit a bug" +msgstr "" + +#: rhodecode/templates/base/base.html:111 +msgid "Switch repository" +msgstr "" + +#: rhodecode/templates/base/base.html:113 +msgid "Products" +msgstr "" + +#: rhodecode/templates/base/base.html:119 +msgid "loading..." +msgstr "" + +#: rhodecode/templates/base/base.html:185 rhodecode/templates/base/base.html:187 +#: rhodecode/templates/base/base.html:189 +#: rhodecode/templates/summary/summary.html:4 +msgid "Summary" +msgstr "" + +#: rhodecode/templates/base/base.html:201 rhodecode/templates/base/base.html:203 +#: rhodecode/templates/base/base.html:205 +#: rhodecode/templates/changelog/changelog.html:6 +#: rhodecode/templates/changelog/changelog.html:14 +msgid "Changelog" +msgstr "" + +#: rhodecode/templates/base/base.html:210 rhodecode/templates/base/base.html:212 +#: rhodecode/templates/base/base.html:214 +msgid "Switch to" +msgstr "" + +#: rhodecode/templates/base/base.html:218 +#: rhodecode/templates/branches/branches.html:13 +msgid "branches" +msgstr "" + +#: rhodecode/templates/base/base.html:225 +#: rhodecode/templates/branches/branches_data.html:32 +msgid "There are no branches yet" +msgstr "" + +#: rhodecode/templates/base/base.html:230 +#: rhodecode/templates/shortlog/shortlog_data.html:10 +#: rhodecode/templates/tags/tags.html:14 +msgid "tags" +msgstr "" + +#: rhodecode/templates/base/base.html:237 +#: rhodecode/templates/tags/tags_data.html:32 +msgid "There are no tags yet" +msgstr "" + +#: rhodecode/templates/base/base.html:244 rhodecode/templates/base/base.html:246 +#: rhodecode/templates/base/base.html:248 rhodecode/templates/files/files.html:4 +msgid "Files" +msgstr "" + +#: rhodecode/templates/base/base.html:253 rhodecode/templates/base/base.html:257 +#: rhodecode/templates/files/files_annotate.html:40 +#: rhodecode/templates/files/files_source.html:11 +msgid "Options" +msgstr "" + +#: rhodecode/templates/base/base.html:262 rhodecode/templates/base/base.html:264 +#: rhodecode/templates/base/base.html:281 +msgid "settings" +msgstr "" + +#: rhodecode/templates/base/base.html:268 +msgid "search" +msgstr "" + +#: rhodecode/templates/base/base.html:275 +msgid "journal" +msgstr "" + +#: rhodecode/templates/base/base.html:277 +msgid "users" +msgstr "" + +#: rhodecode/templates/base/base.html:278 +msgid "users groups" +msgstr "" + +#: rhodecode/templates/base/base.html:279 +msgid "permissions" +msgstr "" + +#: rhodecode/templates/base/base.html:293 rhodecode/templates/base/base.html:295 +msgid "Followers" +msgstr "" + +#: rhodecode/templates/base/base.html:301 rhodecode/templates/base/base.html:303 +msgid "Forks" +msgstr "" + +#: rhodecode/templates/base/base.html:334 rhodecode/templates/base/base.html:336 +#: rhodecode/templates/base/base.html:338 rhodecode/templates/search/search.html:4 +#: rhodecode/templates/search/search.html:24 +#: rhodecode/templates/search/search.html:46 +msgid "Search" +msgstr "" + +#: rhodecode/templates/base/root.html:80 +#: rhodecode/templates/journal/journal.html:48 +#: rhodecode/templates/summary/summary.html:36 +msgid "Stop following this repository" +msgstr "" + +#: rhodecode/templates/base/root.html:90 +#: rhodecode/templates/summary/summary.html:40 +msgid "Start following this repository" +msgstr "" + +#: rhodecode/templates/branches/branches_data.html:4 +#: rhodecode/templates/tags/tags_data.html:4 +msgid "date" +msgstr "" + +#: rhodecode/templates/branches/branches_data.html:6 +#: rhodecode/templates/shortlog/shortlog_data.html:7 +#: rhodecode/templates/tags/tags_data.html:6 +msgid "author" +msgstr "" + +#: rhodecode/templates/branches/branches_data.html:8 +#: rhodecode/templates/shortlog/shortlog_data.html:11 +#: rhodecode/templates/tags/tags_data.html:8 +msgid "links" +msgstr "" + +#: rhodecode/templates/branches/branches_data.html:24 +#: rhodecode/templates/shortlog/shortlog_data.html:39 +#: rhodecode/templates/tags/tags_data.html:24 +msgid "changeset" +msgstr "" + +#: rhodecode/templates/branches/branches_data.html:26 +#: rhodecode/templates/files/files.html:12 +#: rhodecode/templates/shortlog/shortlog_data.html:41 +#: rhodecode/templates/summary/summary.html:225 +#: rhodecode/templates/tags/tags_data.html:26 +msgid "files" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:14 +msgid "showing " +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:14 +msgid "out of" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:37 +msgid "Show" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:40 +msgid "set" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:52 +#: rhodecode/templates/changeset/changeset.html:42 +#: rhodecode/templates/summary/summary.html:613 +msgid "commit" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:66 +#: rhodecode/templates/changeset/changeset.html:55 +msgid "removed" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:67 +#: rhodecode/templates/changeset/changeset.html:56 +msgid "changed" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:68 +#: rhodecode/templates/changeset/changeset.html:57 +msgid "added" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:70 +#: rhodecode/templates/changelog/changelog.html:71 +#: rhodecode/templates/changelog/changelog.html:72 +#: rhodecode/templates/changeset/changeset.html:59 +#: rhodecode/templates/changeset/changeset.html:60 +#: rhodecode/templates/changeset/changeset.html:61 +#, python-format +msgid "affected %s files" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:77 +#: rhodecode/templates/changeset/changeset.html:66 +msgid "merge" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:82 +#: rhodecode/templates/changeset/changeset.html:72 +msgid "Parent" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:87 +#: rhodecode/templates/changeset/changeset.html:77 +msgid "No parents" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:92 +#: rhodecode/templates/changeset/changeset.html:80 +#: rhodecode/templates/files/files.html:29 +#: rhodecode/templates/files/files_annotate.html:25 +#: rhodecode/templates/shortlog/shortlog_data.html:9 +msgid "branch" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:96 +#: rhodecode/templates/changeset/changeset.html:83 +msgid "tag" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:132 +msgid "Show selected changes __S -> __E" +msgstr "" + +#: rhodecode/templates/changelog/changelog.html:163 +#: rhodecode/templates/shortlog/shortlog_data.html:65 +msgid "There are no changes yet" +msgstr "" + +#: rhodecode/templates/changeset/changeset.html:6 +#: rhodecode/templates/changeset/changeset.html:14 +#: rhodecode/templates/changeset/changeset.html:31 +msgid "Changeset" +msgstr "" + +#: rhodecode/templates/changeset/changeset.html:32 +#: rhodecode/templates/changeset/changeset.html:121 +#: rhodecode/templates/changeset/changeset_range.html:78 +#: rhodecode/templates/files/file_diff.html:32 +msgid "raw diff" +msgstr "" + +#: rhodecode/templates/changeset/changeset.html:34 +#: rhodecode/templates/changeset/changeset.html:123 +#: rhodecode/templates/changeset/changeset_range.html:80 +#: rhodecode/templates/files/file_diff.html:34 +msgid "download diff" +msgstr "" + +#: rhodecode/templates/changeset/changeset.html:90 +#, python-format +msgid "%s files affected with %s additions and %s deletions." +msgstr "" + +#: rhodecode/templates/changeset/changeset.html:101 +msgid "Changeset was to big and was cut off..." +msgstr "" + +#: rhodecode/templates/changeset/changeset.html:119 +#: rhodecode/templates/changeset/changeset_range.html:76 +#: rhodecode/templates/files/file_diff.html:30 +msgid "diff" +msgstr "" + +#: rhodecode/templates/changeset/changeset.html:132 +#: rhodecode/templates/changeset/changeset_range.html:89 +msgid "No changes in this file" +msgstr "" + +#: rhodecode/templates/changeset/changeset_range.html:30 +msgid "Compare View" +msgstr "" + +#: rhodecode/templates/changeset/changeset_range.html:52 +msgid "Files affected" +msgstr "" + +#: rhodecode/templates/errors/error_document.html:44 +#, python-format +msgid "You will be redirected to %s in %s seconds" +msgstr "" + +#: rhodecode/templates/files/file_diff.html:4 +#: rhodecode/templates/files/file_diff.html:12 +msgid "File diff" +msgstr "" + +#: rhodecode/templates/files/file_diff.html:40 +msgid "No changes" +msgstr "" + +#: rhodecode/templates/files/files.html:37 +#: rhodecode/templates/files/files_annotate.html:31 +msgid "Location" +msgstr "" + +#: rhodecode/templates/files/files.html:46 +msgid "Go back" +msgstr "" + +#: rhodecode/templates/files/files.html:47 +msgid "No files at given path" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:4 +msgid "File annotate" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:12 +msgid "annotate" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:33 +#: rhodecode/templates/files/files_browser.html:47 +#: rhodecode/templates/files/files_source.html:2 +msgid "Revision" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:36 +#: rhodecode/templates/files/files_browser.html:45 +#: rhodecode/templates/files/files_source.html:7 +msgid "Size" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:38 +#: rhodecode/templates/files/files_browser.html:46 +#: rhodecode/templates/files/files_source.html:9 +msgid "Mimetype" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:41 +msgid "show source" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:43 +#: rhodecode/templates/files/files_annotate.html:72 +#: rhodecode/templates/files/files_source.html:14 +#: rhodecode/templates/files/files_source.html:45 +msgid "show as raw" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:45 +#: rhodecode/templates/files/files_source.html:16 +msgid "download as raw" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:48 +#: rhodecode/templates/files/files_source.html:19 +msgid "History" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:67 +#: rhodecode/templates/files/files_source.html:40 +#, python-format +msgid "Binary file (%s)" +msgstr "" + +#: rhodecode/templates/files/files_annotate.html:72 +#: rhodecode/templates/files/files_source.html:45 +msgid "File is to big to display" +msgstr "" + +#: rhodecode/templates/files/files_browser.html:13 +msgid "view" +msgstr "" + +#: rhodecode/templates/files/files_browser.html:14 +msgid "previous revision" +msgstr "" + +#: rhodecode/templates/files/files_browser.html:16 +msgid "next revision" +msgstr "" + +#: rhodecode/templates/files/files_browser.html:23 +msgid "follow current branch" +msgstr "" + +#: rhodecode/templates/files/files_browser.html:48 +msgid "Last modified" +msgstr "" + +#: rhodecode/templates/files/files_browser.html:49 +msgid "Last commiter" +msgstr "" + +#: rhodecode/templates/files/files_source.html:12 +msgid "show annotation" +msgstr "" + +#: rhodecode/templates/journal/journal.html:34 +msgid "Following" +msgstr "" + +#: rhodecode/templates/journal/journal.html:41 +msgid "following user" +msgstr "" + +#: rhodecode/templates/journal/journal.html:41 +msgid "user" +msgstr "" + +#: rhodecode/templates/journal/journal.html:65 +msgid "You are not following any users or repositories" +msgstr "" + +#: rhodecode/templates/journal/journal_data.html:52 +msgid "No entries yet" +msgstr "" + +#: rhodecode/templates/journal/public_journal.html:17 +msgid "Public Journal" +msgstr "" + +#: rhodecode/templates/search/search.html:7 +#: rhodecode/templates/search/search.html:26 +msgid "in repository: " +msgstr "" + +#: rhodecode/templates/search/search.html:9 +#: rhodecode/templates/search/search.html:28 +msgid "in all repositories" +msgstr "" + +#: rhodecode/templates/search/search.html:42 +msgid "Search term" +msgstr "" + +#: rhodecode/templates/search/search.html:54 +msgid "Search in" +msgstr "" + +#: rhodecode/templates/search/search.html:57 +msgid "File contents" +msgstr "" + +#: rhodecode/templates/search/search.html:59 +msgid "File names" +msgstr "" + +#: rhodecode/templates/search/search_content.html:20 +#: rhodecode/templates/search/search_path.html:15 +msgid "Permission denied" +msgstr "" + +#: rhodecode/templates/settings/repo_fork.html:5 +msgid "Fork" +msgstr "" + +#: rhodecode/templates/settings/repo_fork.html:31 +msgid "Fork name" +msgstr "" + +#: rhodecode/templates/shortlog/shortlog.html:5 +#: rhodecode/templates/summary/summary.html:670 +msgid "Shortlog" +msgstr "" + +#: rhodecode/templates/shortlog/shortlog.html:14 +msgid "shortlog" +msgstr "" + +#: rhodecode/templates/shortlog/shortlog_data.html:5 +msgid "commit message" +msgstr "" + +#: rhodecode/templates/shortlog/shortlog_data.html:6 +msgid "age" +msgstr "" + +#: rhodecode/templates/summary/summary.html:12 +msgid "summary" +msgstr "" + +#: rhodecode/templates/summary/summary.html:79 +msgid "remote clone" +msgstr "" + +#: rhodecode/templates/summary/summary.html:123 +msgid "by" +msgstr "" + +#: rhodecode/templates/summary/summary.html:130 +msgid "Clone url" +msgstr "" + +#: rhodecode/templates/summary/summary.html:139 +msgid "Trending source files" +msgstr "" + +#: rhodecode/templates/summary/summary.html:148 +msgid "Download" +msgstr "" + +#: rhodecode/templates/summary/summary.html:152 +msgid "There are no downloads yet" +msgstr "" + +#: rhodecode/templates/summary/summary.html:154 +msgid "Downloads are disabled for this repository" +msgstr "" + +#: rhodecode/templates/summary/summary.html:156 +#: rhodecode/templates/summary/summary.html:309 +msgid "enable" +msgstr "" + +#: rhodecode/templates/summary/summary.html:164 +#: rhodecode/templates/summary/summary.html:287 +#, python-format +msgid "Download %s as %s" +msgstr "" + +#: rhodecode/templates/summary/summary.html:175 +msgid "Feeds" +msgstr "" + +#: rhodecode/templates/summary/summary.html:248 +#: rhodecode/templates/summary/summary.html:688 +#: rhodecode/templates/summary/summary.html:699 +msgid "show more" +msgstr "" + +#: rhodecode/templates/summary/summary.html:301 +msgid "Commit activity by day / author" +msgstr "" + +#: rhodecode/templates/summary/summary.html:313 +msgid "Loaded in" +msgstr "" + +#: rhodecode/templates/summary/summary.html:607 +msgid "commits" +msgstr "" + +#: rhodecode/templates/summary/summary.html:608 +msgid "files added" +msgstr "" + +#: rhodecode/templates/summary/summary.html:609 +msgid "files changed" +msgstr "" + +#: rhodecode/templates/summary/summary.html:610 +msgid "files removed" +msgstr "" + +#: rhodecode/templates/summary/summary.html:614 +msgid "file added" +msgstr "" + +#: rhodecode/templates/summary/summary.html:615 +msgid "file changed" +msgstr "" + +#: rhodecode/templates/summary/summary.html:616 +msgid "file removed" +msgstr "" +
--- a/rhodecode/lib/base.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/base.py Tue Apr 26 14:03:00 2011 +0200 @@ -62,7 +62,8 @@ c.rhodecode_repo, dbrepo = self.scm_model.get(c.repo_name, retval='repo') - if c.rhodecode_repo: + + if c.rhodecode_repo is not None: c.repository_followers = self.scm_model.get_followers(c.repo_name) c.repository_forks = self.scm_model.get_forks(c.repo_name) else:
--- a/rhodecode/lib/celerylib/__init__.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/celerylib/__init__.py Tue Apr 26 14:03:00 2011 +0200 @@ -48,6 +48,7 @@ except KeyError: CELERY_ON = False + class ResultWrapper(object): def __init__(self, task): self.task = task @@ -56,12 +57,14 @@ def result(self): return self.task + def run_task(task, *args, **kwargs): if CELERY_ON: try: t = task.apply_async(args=args, kwargs=kwargs) log.info('running task %s:%s', t.task_id, task) return t + except socket.error, e: if e.errno == 111: log.debug('Unable to connect to celeryd. Sync execution') @@ -76,14 +79,20 @@ return ResultWrapper(task(*args, **kwargs)) +def __get_lockkey(func, *fargs, **fkwargs): + params = list(fargs) + params.extend(['%s-%s' % ar for ar in fkwargs.items()]) + + func_name = str(func.__name__) if hasattr(func, '__name__') else str(func) + + lockkey = 'task_%s' % \ + md5(func_name + '-' + '-'.join(map(str, params))).hexdigest() + return lockkey + + def locked_task(func): def __wrapper(func, *fargs, **fkwargs): - params = list(fargs) - params.extend(['%s-%s' % ar for ar in fkwargs.items()]) - - lockkey = 'task_%s' % \ - md5(str(func.__name__) + '-' + \ - '-'.join(map(str, params))).hexdigest() + lockkey = __get_lockkey(func, *fargs, **fkwargs) log.info('running task with lockkey %s', lockkey) try: l = DaemonLock(lockkey)
--- a/rhodecode/lib/celerylib/tasks.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/celerylib/tasks.py Tue Apr 26 14:03:00 2011 +0200 @@ -37,13 +37,14 @@ from pylons import config from pylons.i18n.translation import _ -from rhodecode.lib.celerylib import run_task, locked_task, str2bool +from rhodecode.lib.celerylib import run_task, locked_task, str2bool, \ + __get_lockkey, LockHeld, DaemonLock from rhodecode.lib.helpers import person from rhodecode.lib.smtp_mailer import SmtpMailer from rhodecode.lib.utils import OrderedDict, add_cache from rhodecode.model import init_model from rhodecode.model import meta -from rhodecode.model.db import RhodeCodeUi +from rhodecode.model.db import RhodeCodeUi, Statistics, Repository from vcs.backends import get_repo @@ -125,146 +126,162 @@ @task(ignore_result=True) -@locked_task def get_commits_stats(repo_name, ts_min_y, ts_max_y): try: log = get_commits_stats.get_logger() except: log = logging.getLogger(__name__) - from rhodecode.model.db import Statistics, Repository + lockkey = __get_lockkey('get_commits_stats', repo_name, ts_min_y, + ts_max_y) + log.info('running task with lockkey %s', lockkey) + try: + lock = DaemonLock(lockkey) - #for js data compatibilty - akc = lambda k: person(k).replace('"', "") + #for js data compatibilty cleans the key for person from ' + akc = lambda k: person(k).replace('"', "") - co_day_auth_aggr = {} - commits_by_day_aggregate = {} - repos_path = get_repos_path() - p = os.path.join(repos_path, repo_name) - repo = get_repo(p) + co_day_auth_aggr = {} + commits_by_day_aggregate = {} + repos_path = get_repos_path() + p = os.path.join(repos_path, repo_name) + repo = get_repo(p) + repo_size = len(repo.revisions) + #return if repo have no revisions + if repo_size < 1: + lock.release() + return True - skip_date_limit = True - parse_limit = int(config['app_conf'].get('commit_parse_limit')) - last_rev = 0 - last_cs = None - timegetter = itemgetter('time') + skip_date_limit = True + parse_limit = int(config['app_conf'].get('commit_parse_limit')) + last_rev = 0 + last_cs = None + timegetter = itemgetter('time') - sa = get_session() + sa = get_session() - dbrepo = sa.query(Repository)\ - .filter(Repository.repo_name == repo_name).scalar() - cur_stats = sa.query(Statistics)\ - .filter(Statistics.repository == dbrepo).scalar() + dbrepo = sa.query(Repository)\ + .filter(Repository.repo_name == repo_name).scalar() + cur_stats = sa.query(Statistics)\ + .filter(Statistics.repository == dbrepo).scalar() - if cur_stats is not None: - last_rev = cur_stats.stat_on_revision + if cur_stats is not None: + last_rev = cur_stats.stat_on_revision - #return if repo is empty - if not repo.revisions: - return True + if last_rev == repo.get_changeset().revision and repo_size > 1: + #pass silently without any work if we're not on first revision or + #current state of parsing revision(from db marker) is the + #last revision + lock.release() + return True - if last_rev == repo.get_changeset().revision and len(repo.revisions) > 1: - #pass silently without any work if we're not on first revision or - #current state of parsing revision(from db marker) is the last revision - return True + if cur_stats: + commits_by_day_aggregate = OrderedDict(json.loads( + cur_stats.commit_activity_combined)) + co_day_auth_aggr = json.loads(cur_stats.commit_activity) - if cur_stats: - commits_by_day_aggregate = OrderedDict( - json.loads( - cur_stats.commit_activity_combined)) - co_day_auth_aggr = json.loads(cur_stats.commit_activity) + log.debug('starting parsing %s', parse_limit) + lmktime = mktime + + last_rev = last_rev + 1 if last_rev > 0 else last_rev - log.debug('starting parsing %s', parse_limit) - lmktime = mktime - - last_rev = last_rev + 1 if last_rev > 0 else last_rev + for cs in repo[last_rev:last_rev + parse_limit]: + last_cs = cs # remember last parsed changeset + k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1], + cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0]) - for cs in repo[last_rev:last_rev + parse_limit]: - last_cs = cs # remember last parsed changeset - k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1], - cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0]) + if akc(cs.author) in co_day_auth_aggr: + try: + l = [timegetter(x) for x in + co_day_auth_aggr[akc(cs.author)]['data']] + time_pos = l.index(k) + except ValueError: + time_pos = False + + if time_pos >= 0 and time_pos is not False: + + datadict = \ + co_day_auth_aggr[akc(cs.author)]['data'][time_pos] - if akc(cs.author) in co_day_auth_aggr: - try: - l = [timegetter(x) for x in - co_day_auth_aggr[akc(cs.author)]['data']] - time_pos = l.index(k) - except ValueError: - time_pos = False + datadict["commits"] += 1 + datadict["added"] += len(cs.added) + datadict["changed"] += len(cs.changed) + datadict["removed"] += len(cs.removed) + + else: + if k >= ts_min_y and k <= ts_max_y or skip_date_limit: - if time_pos >= 0 and time_pos is not False: - - datadict = co_day_auth_aggr[akc(cs.author)]['data'][time_pos] - - datadict["commits"] += 1 - datadict["added"] += len(cs.added) - datadict["changed"] += len(cs.changed) - datadict["removed"] += len(cs.removed) + datadict = {"time": k, + "commits": 1, + "added": len(cs.added), + "changed": len(cs.changed), + "removed": len(cs.removed), + } + co_day_auth_aggr[akc(cs.author)]['data']\ + .append(datadict) else: if k >= ts_min_y and k <= ts_max_y or skip_date_limit: - - datadict = {"time": k, - "commits": 1, - "added": len(cs.added), - "changed": len(cs.changed), - "removed": len(cs.removed), - } - co_day_auth_aggr[akc(cs.author)]['data']\ - .append(datadict) + co_day_auth_aggr[akc(cs.author)] = { + "label": akc(cs.author), + "data": [{"time":k, + "commits":1, + "added":len(cs.added), + "changed":len(cs.changed), + "removed":len(cs.removed), + }], + "schema": ["commits"], + } - else: - if k >= ts_min_y and k <= ts_max_y or skip_date_limit: - co_day_auth_aggr[akc(cs.author)] = { - "label": akc(cs.author), - "data": [{"time":k, - "commits":1, - "added":len(cs.added), - "changed":len(cs.changed), - "removed":len(cs.removed), - }], - "schema": ["commits"], - } + #gather all data by day + if k in commits_by_day_aggregate: + commits_by_day_aggregate[k] += 1 + else: + commits_by_day_aggregate[k] = 1 - #gather all data by day - if k in commits_by_day_aggregate: - commits_by_day_aggregate[k] += 1 - else: - commits_by_day_aggregate[k] = 1 + overview_data = sorted(commits_by_day_aggregate.items(), + key=itemgetter(0)) + + if not co_day_auth_aggr: + co_day_auth_aggr[akc(repo.contact)] = { + "label": akc(repo.contact), + "data": [0, 1], + "schema": ["commits"], + } - overview_data = sorted(commits_by_day_aggregate.items(), key=itemgetter(0)) - if not co_day_auth_aggr: - co_day_auth_aggr[akc(repo.contact)] = { - "label": akc(repo.contact), - "data": [0, 1], - "schema": ["commits"], - } + stats = cur_stats if cur_stats else Statistics() + stats.commit_activity = json.dumps(co_day_auth_aggr) + stats.commit_activity_combined = json.dumps(overview_data) - stats = cur_stats if cur_stats else Statistics() - stats.commit_activity = json.dumps(co_day_auth_aggr) - stats.commit_activity_combined = json.dumps(overview_data) + log.debug('last revison %s', last_rev) + leftovers = len(repo.revisions[last_rev:]) + log.debug('revisions to parse %s', leftovers) - log.debug('last revison %s', last_rev) - leftovers = len(repo.revisions[last_rev:]) - log.debug('revisions to parse %s', leftovers) + if last_rev == 0 or leftovers < parse_limit: + log.debug('getting code trending stats') + stats.languages = json.dumps(__get_codes_stats(repo_name)) - if last_rev == 0 or leftovers < parse_limit: - log.debug('getting code trending stats') - stats.languages = json.dumps(__get_codes_stats(repo_name)) + try: + stats.repository = dbrepo + stats.stat_on_revision = last_cs.revision if last_cs else 0 + sa.add(stats) + sa.commit() + except: + log.error(traceback.format_exc()) + sa.rollback() + lock.release() + return False - try: - stats.repository = dbrepo - stats.stat_on_revision = last_cs.revision if last_cs else 0 - sa.add(stats) - sa.commit() - except: - log.error(traceback.format_exc()) - sa.rollback() - return False - if len(repo.revisions) > 1: - run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y) + #final release + lock.release() - return True + #execute another task if celery is enabled + if len(repo.revisions) > 1 and CELERY_ON: + run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y) + return True + except LockHeld: + log.info('LockHeld') + return 'Task with key %s already running' % lockkey @task(ignore_result=True) @@ -313,7 +330,6 @@ """ Sends an email with defined parameters from the .ini files. - :param recipients: list of recipients, it this is empty the defined email address from field 'email_to' is used instead :param subject: subject of the mail @@ -351,14 +367,14 @@ @task(ignore_result=True) def create_repo_fork(form_data, cur_user): + from rhodecode.model.repo import RepoModel + from vcs import get_backend + try: log = create_repo_fork.get_logger() except: log = logging.getLogger(__name__) - from rhodecode.model.repo import RepoModel - from vcs import get_backend - repo_model = RepoModel(get_session()) repo_model.create(form_data, cur_user, just_db=True, fork=True) repo_name = form_data['repo_name']
--- a/rhodecode/lib/db_manage.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/db_manage.py Tue Apr 26 14:03:00 2011 +0200 @@ -36,13 +36,14 @@ from rhodecode.lib.auth import get_crypt_password, generate_api_key from rhodecode.lib.utils import ask_ok from rhodecode.model import init_model -from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \ - UserToPerm, DbMigrateVersion +from rhodecode.model.db import User, Permission, RhodeCodeUi, \ + RhodeCodeSettings, UserToPerm, DbMigrateVersion from sqlalchemy.engine import create_engine log = logging.getLogger(__name__) + class DbManage(object): def __init__(self, log_sql, dbconf, root, tests=False): self.dbname = dbconf.split('/')[-1] @@ -76,8 +77,6 @@ meta.Base.metadata.create_all(checkfirst=checkfirst) log.info('Created tables for %s', self.dbname) - - def set_db_version(self): try: ver = DbMigrateVersion() @@ -91,7 +90,6 @@ raise log.info('db version set to: %s', __dbversion__) - def upgrade(self): """Upgrades given database schema to given revision following all needed steps, to perform the upgrade @@ -170,8 +168,6 @@ print ('performing upgrade step %s' % step) callable = getattr(UpgradeSteps(self), 'step_%s' % step)() - - def fix_repo_paths(self): """Fixes a old rhodecode version path into new one without a '*' """ @@ -225,9 +221,9 @@ if not self.tests: import getpass - def get_password(): - password = getpass.getpass('Specify admin password (min 6 chars):') + password = getpass.getpass('Specify admin password ' + '(min 6 chars):') confirm = getpass.getpass('Confirm password:') if password != confirm: @@ -252,9 +248,12 @@ self.create_user(username, password, email, True) else: log.info('creating admin and regular test users') - self.create_user('test_admin', 'test12', 'test_admin@mail.com', True) - self.create_user('test_regular', 'test12', 'test_regular@mail.com', False) - self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False) + self.create_user('test_admin', 'test12', + 'test_admin@mail.com', True) + self.create_user('test_regular', 'test12', + 'test_regular@mail.com', False) + self.create_user('test_regular2', 'test12', + 'test_regular2@mail.com', False) def create_ui_settings(self): """Creates ui settings, fills out hooks @@ -308,7 +307,6 @@ self.sa.rollback() raise - def create_ldap_options(self): """Creates ldap settings""" @@ -321,7 +319,6 @@ ('ldap_attr_login', ''), ('ldap_attr_firstname', ''), ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]: - setting = RhodeCodeSettings(k, v) self.sa.add(setting) self.sa.commit() @@ -353,14 +350,12 @@ log.error('No write permission to given path: %s [%s/3]', path, retries) - if retries == 0: sys.exit() if path_ok is False: retries -= 1 return self.config_prompt(test_repo_path, retries) - return path def create_settings(self, path): @@ -393,12 +388,10 @@ paths.ui_key = '/' paths.ui_value = path - hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication') hgsettings2 = RhodeCodeSettings('title', 'RhodeCode') hgsettings3 = RhodeCodeSettings('ga_code', '') - try: self.sa.add(web1) self.sa.add(web2) @@ -467,8 +460,13 @@ ('hg.create.repository', 'Repository create'), ('hg.create.none', 'Repository creation disabled'), ('hg.register.none', 'Register disabled'), - ('hg.register.manual_activate', 'Register new user with RhodeCode without manual activation'), - ('hg.register.auto_activate', 'Register new user with RhodeCode without auto activation'), + ('hg.register.manual_activate', 'Register new user with ' + 'RhodeCode without manual' + 'activation'), + + ('hg.register.auto_activate', 'Register new user with ' + 'RhodeCode without auto ' + 'activation'), ] for p in perms:
--- a/rhodecode/lib/dbmigrate/versions/003_version_1_2_0.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/dbmigrate/versions/003_version_1_2_0.py Tue Apr 26 14:03:00 2011 +0200 @@ -10,7 +10,6 @@ from rhodecode.lib.dbmigrate.migrate.changeset import * from rhodecode.model.meta import Base -from rhodecode.model.db import BaseModel log = logging.getLogger(__name__) @@ -44,12 +43,17 @@ UsersGroupMember().__table__.create() #========================================================================== + # Add table `users_group_repo_to_perm` + #========================================================================== + from rhodecode.model.db import UsersGroupRepoToPerm + UsersGroupRepoToPerm().__table__.create() + + #========================================================================== # Add table `users_group_to_perm` #========================================================================== from rhodecode.model.db import UsersGroupToPerm UsersGroupToPerm().__table__.create() - #========================================================================== # Upgrade of `users` table #==========================================================================
--- a/rhodecode/lib/helpers.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/helpers.py Tue Apr 26 14:03:00 2011 +0200 @@ -622,7 +622,8 @@ suf = '' if len(nodes) > 30: suf = '<br/>' + _(' and %s more') % (len(nodes) - 30) - return literal(pref + '<br/> '.join([safe_unicode(x.path) for x in nodes[:30]]) + suf) + return literal(pref + '<br/> '.join([safe_unicode(x.path) + for x in nodes[:30]]) + suf) else: return ': ' + _('No Files') @@ -635,6 +636,56 @@ return repo_name else: def make_link(group): - return link_to(group.group_name, url('repos_group', id=group.group_id)) + return link_to(group.group_name, url('repos_group', + id=group.group_id)) return literal(' » '.join(map(make_link, groups)) + \ " » " + repo_name) + + +def fancy_file_stats(stats): + a, d, t = stats[0], stats[1], stats[0] + stats[1] + width = 100 + unit = float(width) / (t or 1) + + a_p = max(9, unit * a) if a > 0 else 0# needs > 9% to be visible + d_p = max(9, unit * d) if d > 0 else 0 # needs > 9% to be visible + 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) + else: + 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: + return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl'])) + + + + 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))
--- a/rhodecode/lib/middleware/https_fixup.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/middleware/https_fixup.py Tue Apr 26 14:03:00 2011 +0200 @@ -25,7 +25,9 @@ from rhodecode.lib import str2bool + class HttpsFixup(object): + def __init__(self, app, config): self.application = app self.config = config @@ -34,9 +36,9 @@ self.__fixup(environ) return self.application(environ, start_response) - def __fixup(self, environ): - """Function to fixup the environ as needed. In order to use this + """ + Function to fixup the environ as needed. In order to use this middleware you should set this header inside your proxy ie. nginx, apache etc. """
--- a/rhodecode/lib/middleware/simplegit.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/middleware/simplegit.py Tue Apr 26 14:03:00 2011 +0200 @@ -30,13 +30,15 @@ from dulwich import server as dulserver + class SimpleGitUploadPackHandler(dulserver.UploadPackHandler): def handle(self): write = lambda x: self.proto.write_sideband(1, x) - graph_walker = dulserver.ProtocolGraphWalker(self, self.repo.object_store, - self.repo.get_peeled) + graph_walker = dulserver.ProtocolGraphWalker(self, + self.repo.object_store, + self.repo.get_peeled) objects_iter = self.repo.fetch_objects( graph_walker.determine_wants, graph_walker, self.progress, get_tagged=self.get_tagged) @@ -46,8 +48,8 @@ return self.progress("counting objects: %d, done.\n" % len(objects_iter)) - dulserver.write_pack_data(dulserver.ProtocolFile(None, write), objects_iter, - len(objects_iter)) + dulserver.write_pack_data(dulserver.ProtocolFile(None, write), + objects_iter, len(objects_iter)) messages = [] messages.append('thank you for using rhodecode') @@ -75,6 +77,7 @@ log = logging.getLogger(__name__) + def is_git(environ): """Returns True if request's target is git server. ``HTTP_USER_AGENT`` would then have git client version given. @@ -86,6 +89,7 @@ return True return False + class SimpleGit(object): def __init__(self, application, config): @@ -123,16 +127,17 @@ #====================================================================== # CHECK ANONYMOUS PERMISSION #====================================================================== - if self.action in ['pull', 'push'] or self.action: + if self.action in ['pull', 'push']: anonymous_user = self.__get_user('default') self.username = anonymous_user.username - anonymous_perm = self.__check_permission(self.action, anonymous_user , - self.repo_name) + anonymous_perm = self.__check_permission(self.action, + anonymous_user, + self.repo_name) if anonymous_perm is not True or anonymous_user.active is False: if anonymous_perm is not True: - log.debug('Not enough credentials to access this repository' - 'as anonymous user') + log.debug('Not enough credentials to access this ' + 'repository as anonymous user') if anonymous_user.active is False: log.debug('Anonymous access is disabled, running ' 'authentication') @@ -142,7 +147,8 @@ #============================================================== if not REMOTE_USER(environ): - self.authenticate.realm = str(self.config['rhodecode_realm']) + self.authenticate.realm = str( + self.config['rhodecode_realm']) result = self.authenticate(environ) if isinstance(result, str): AUTH_TYPE.update(environ, 'basic') @@ -150,31 +156,31 @@ else: return result.wsgi_application(environ, start_response) - #============================================================== # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM # BASIC AUTH #============================================================== - if self.action in ['pull', 'push'] or self.action: + if self.action in ['pull', 'push']: username = REMOTE_USER(environ) try: user = self.__get_user(username) self.username = user.username except: log.error(traceback.format_exc()) - return HTTPInternalServerError()(environ, start_response) + return HTTPInternalServerError()(environ, + start_response) #check permissions for this repository - perm = self.__check_permission(self.action, user, self.repo_name) + perm = self.__check_permission(self.action, user, + self.repo_name) if perm is not True: - print 'not allowed' return HTTPForbidden()(environ, start_response) - self.extras = {'ip':self.ipaddr, - 'username':self.username, - 'action':self.action, - 'repository':self.repo_name} + self.extras = {'ip': self.ipaddr, + 'username': self.username, + 'action': self.action, + 'repository': self.repo_name} #=================================================================== # GIT REQUEST HANDLING @@ -193,15 +199,12 @@ #invalidate cache on push if self.action == 'push': self.__invalidate_cache(self.repo_name) - messages = [] - messages.append('thank you for using rhodecode') - return app(environ, start_response) - else: - return app(environ, start_response) + return app(environ, start_response) def __make_app(self): - backend = dulserver.DictBackend({'/' + self.repo_name: Repo(self.repo_path)}) + _d = {'/' + self.repo_name: Repo(self.repo_path)} + backend = dulserver.DictBackend(_d) gitserve = HTTPGitApplication(backend) return gitserve @@ -216,21 +219,20 @@ """ if action == 'push': if not HasPermissionAnyMiddleware('repository.write', - 'repository.admin')\ - (user, repo_name): + 'repository.admin')(user, + repo_name): return False else: #any other action need at least read permission if not HasPermissionAnyMiddleware('repository.read', 'repository.write', - 'repository.admin')\ - (user, repo_name): + 'repository.admin')(user, + repo_name): return False return True - def __get_repository(self, environ): """Get's repository name out of PATH_INFO header @@ -246,7 +248,6 @@ repo_name = repo_name.split('/')[0] return repo_name - def __get_user(self, username): return UserModel().get_by_username(username, cache=True) @@ -262,7 +263,8 @@ 'git-upload-pack': 'pull', } - return mapping.get(service_cmd, service_cmd if service_cmd else 'other') + return mapping.get(service_cmd, + service_cmd if service_cmd else 'other') else: return 'other'
--- a/rhodecode/lib/middleware/simplehg.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/lib/middleware/simplehg.py Tue Apr 26 14:03:00 2011 +0200 @@ -44,6 +44,7 @@ log = logging.getLogger(__name__) + def is_mercurial(environ): """Returns True if request's target is mercurial server - header ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``. @@ -53,6 +54,7 @@ return True return False + class SimpleHg(object): def __init__(self, application, config): @@ -93,13 +95,14 @@ if self.action in ['pull', 'push']: anonymous_user = self.__get_user('default') self.username = anonymous_user.username - anonymous_perm = self.__check_permission(self.action, anonymous_user , - self.repo_name) + anonymous_perm = self.__check_permission(self.action, + anonymous_user, + self.repo_name) if anonymous_perm is not True or anonymous_user.active is False: if anonymous_perm is not True: - log.debug('Not enough credentials to access this repository' - 'as anonymous user') + log.debug('Not enough credentials to access this ' + 'repository as anonymous user') if anonymous_user.active is False: log.debug('Anonymous access is disabled, running ' 'authentication') @@ -109,7 +112,8 @@ #============================================================== if not REMOTE_USER(environ): - self.authenticate.realm = str(self.config['rhodecode_realm']) + self.authenticate.realm = str( + self.config['rhodecode_realm']) result = self.authenticate(environ) if isinstance(result, str): AUTH_TYPE.update(environ, 'basic') @@ -117,7 +121,6 @@ else: return result.wsgi_application(environ, start_response) - #============================================================== # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM # BASIC AUTH @@ -130,22 +133,24 @@ self.username = user.username except: log.error(traceback.format_exc()) - return HTTPInternalServerError()(environ, start_response) + return HTTPInternalServerError()(environ, + start_response) #check permissions for this repository - perm = self.__check_permission(self.action, user, self.repo_name) + perm = self.__check_permission(self.action, user, + self.repo_name) if perm is not True: return HTTPForbidden()(environ, start_response) - self.extras = {'ip':self.ipaddr, - 'username':self.username, - 'action':self.action, - 'repository':self.repo_name} + self.extras = {'ip': self.ipaddr, + 'username': self.username, + 'action': self.action, + 'repository': self.repo_name} - #=================================================================== + #====================================================================== # MERCURIAL REQUEST HANDLING - #=================================================================== - environ['PATH_INFO'] = '/'#since we wrap into hgweb, reset the path + #====================================================================== + environ['PATH_INFO'] = '/' # since we wrap into hgweb, reset the path self.baseui = make_ui('db') self.basepath = self.config['base_path'] self.repo_path = os.path.join(self.basepath, self.repo_name) @@ -168,18 +173,18 @@ return app(environ, start_response) - def __make_app(self): - """Make an wsgi application using hgweb, and my generated baseui - instance """ - - hgserve = hgweb(str(self.repo_path), baseui=self.baseui) - return self.__load_web_settings(hgserve, self.extras) + Make an wsgi application using hgweb, and inject generated baseui + instance, additionally inject some extras into ui object + """ + self.__inject_extras(self.baseui, self.extras) + return hgweb(str(self.repo_path), baseui=self.baseui) def __check_permission(self, action, user, repo_name): - """Checks permissions using action (push/pull) user and repository + """ + Checks permissions using action (push/pull) user and repository name :param action: push or pull action @@ -188,23 +193,23 @@ """ if action == 'push': if not HasPermissionAnyMiddleware('repository.write', - 'repository.admin')\ - (user, repo_name): + 'repository.admin')(user, + repo_name): return False else: #any other action need at least read permission if not HasPermissionAnyMiddleware('repository.read', 'repository.write', - 'repository.admin')\ - (user, repo_name): + 'repository.admin')(user, + repo_name): return False return True - def __get_repository(self, environ): - """Get's repository name out of PATH_INFO header + """ + Get's repository name out of PATH_INFO header :param environ: environ where PATH_INFO is stored """ @@ -222,7 +227,8 @@ return UserModel().get_by_username(username, cache=True) def __get_action(self, environ): - """Maps mercurial request commands into a clone,pull or push command. + """ + Maps mercurial request commands into a clone,pull or push command. This should always return a valid command string :param environ: @@ -236,7 +242,7 @@ for qry in environ['QUERY_STRING'].split('&'): if qry.startswith('cmd'): cmd = qry.split('=')[-1] - if mapping.has_key(cmd): + if cmd in mapping: return mapping[cmd] else: return 'pull' @@ -247,17 +253,14 @@ push requests""" invalidate_cache('get_repo_cached_%s' % repo_name) - - def __load_web_settings(self, hgserve, extras={}): - #set the global ui for hgserve instance passed - hgserve.repo.ui = self.baseui + def __inject_extras(self, baseui, extras={}): hgrc = os.path.join(self.repo_path, '.hg', 'hgrc') #inject some additional parameters that will be available in ui #for hooks for k, v in extras.items(): - hgserve.repo.ui.setconfig('rhodecode_extras', k, v) + baseui.setconfig('rhodecode_extras', k, v) repoui = make_ui('file', hgrc, False) @@ -265,6 +268,4 @@ #overwrite our ui instance with the section from hgrc file for section in ui_sections: for k, v in repoui.configitems(section): - hgserve.repo.ui.setconfig(section, k, v) - - return hgserve + baseui.repo.ui.setconfig(section, k, v)
--- a/rhodecode/model/__init__.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/__init__.py Tue Apr 26 14:03:00 2011 +0200 @@ -47,16 +47,19 @@ log = logging.getLogger(__name__) + def init_model(engine): - """Initializes db session, bind the engine with the metadata, - Call this before using any of the tables or classes in the model, preferably - once in application start + """ + Initializes db session, bind the engine with the metadata, + Call this before using any of the tables or classes in the model, + preferably once in application start :param engine: engine to bind to """ log.info("initializing db for %s", engine) meta.Base.metadata.bind = engine + class BaseModel(object): """Base Model for all RhodeCode models, it adds sql alchemy session into instance of model
--- a/rhodecode/model/caching_query.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/caching_query.py Tue Apr 26 14:03:00 2011 +0200 @@ -18,11 +18,13 @@ Beaker constructs. """ +import beaker from beaker.exceptions import BeakerException + from sqlalchemy.orm.interfaces import MapperOption from sqlalchemy.orm.query import Query from sqlalchemy.sql import visitors -import beaker + class CachingQuery(Query): """A Query subclass which optionally loads full results from a Beaker @@ -74,7 +76,8 @@ """ if hasattr(self, '_cache_parameters'): - return self.get_value(createfunc=lambda: list(Query.__iter__(self))) + return self.get_value(createfunc=lambda: + list(Query.__iter__(self))) else: return Query.__iter__(self) @@ -103,11 +106,13 @@ cache, cache_key = _get_cache_parameters(self) cache.put(cache_key, value) + def query_callable(manager): def query(*arg, **kw): return CachingQuery(manager, *arg, **kw) return query + def get_cache_region(name, region): if region not in beaker.cache.cache_regions: raise BeakerException('Cache region `%s` not configured ' @@ -115,6 +120,7 @@ kw = beaker.cache.cache_regions[region] return beaker.cache.Cache._get_cache(name, kw) + def _get_cache_parameters(query): """For a query with cache_region and cache_namespace configured, return the correspoinding Cache instance and cache key, based @@ -122,7 +128,8 @@ """ if not hasattr(query, '_cache_parameters'): - raise ValueError("This Query does not have caching parameters configured.") + raise ValueError("This Query does not have caching " + "parameters configured.") region, namespace, cache_key = query._cache_parameters @@ -142,6 +149,7 @@ return cache, cache_key + def _namespace_from_query(namespace, query): # cache namespace - the token handed in by the # option + class we're querying against @@ -152,6 +160,7 @@ return namespace + def _set_cache_parameters(query, region, namespace, cache_key): if hasattr(query, '_cache_parameters'): @@ -162,6 +171,7 @@ ) query._cache_parameters = region, namespace, cache_key + class FromCache(MapperOption): """Specifies that a Query should load results from a cache.""" @@ -191,7 +201,9 @@ def process_query(self, query): """Process a Query during normal loading operation.""" - _set_cache_parameters(query, self.region, self.namespace, self.cache_key) + _set_cache_parameters(query, self.region, self.namespace, + self.cache_key) + class RelationshipCache(MapperOption): """Specifies that a Query as called within a "lazy load" @@ -217,7 +229,7 @@ self.region = region self.namespace = namespace self._relationship_options = { - (attribute.property.parent.class_, attribute.property.key) : self + (attribute.property.parent.class_, attribute.property.key): self } def process_query_conditionally(self, query): @@ -232,7 +244,8 @@ for cls in mapper.class_.__mro__: if (cls, key) in self._relationship_options: - relationship_option = self._relationship_options[(cls, key)] + relationship_option = \ + self._relationship_options[(cls, key)] _set_cache_parameters( query, relationship_option.region, @@ -261,6 +274,7 @@ """ v = [] + def visit_bindparam(bind): value = query._params.get(bind.key, bind.value) @@ -272,5 +286,5 @@ v.append(value) if query._criterion is not None: - visitors.traverse(query._criterion, {}, {'bindparam':visit_bindparam}) + visitors.traverse(query._criterion, {}, {'bindparam': visit_bindparam}) return v
--- a/rhodecode/model/db.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/db.py Tue Apr 26 14:03:00 2011 +0200 @@ -33,7 +33,9 @@ from sqlalchemy.orm import relationship, backref from sqlalchemy.orm.interfaces import MapperExtension +from rhodecode.lib import str2bool from rhodecode.model.meta import Base, Session +from rhodecode.model.caching_query import FromCache log = logging.getLogger(__name__) @@ -61,6 +63,35 @@ return "<%s('%s:%s')>" % (self.__class__.__name__, self.app_settings_name, self.app_settings_value) + + @classmethod + def get_app_settings(cls, cache=False): + + ret = Session.query(cls) + + if cache: + ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) + + if not ret: + raise Exception('Could not get application settings !') + settings = {} + for each in ret: + settings['rhodecode_' + each.app_settings_name] = \ + each.app_settings_value + + return settings + + @classmethod + def get_ldap_settings(cls, cache=False): + ret = Session.query(cls)\ + .filter(cls.app_settings_name.startswith('ldap_'))\ + .all() + fd = {} + for row in ret: + fd.update({row.app_settings_name:str2bool(row.app_settings_value)}) + return fd + + class RhodeCodeUi(Base): __tablename__ = 'rhodecode_ui' __table_args__ = {'useexisting':True} @@ -158,6 +189,20 @@ members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined") + + @classmethod + def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): + if case_insensitive: + gr = Session.query(cls)\ + .filter(cls.users_group_name.ilike(group_name)) + else: + gr = Session.query(UsersGroup)\ + .filter(UsersGroup.users_group_name == group_name) + if cache: + gr = gr.options(FromCache("sql_cache_short", + "get_user_%s" % group_name)) + return gr.scalar() + class UsersGroupMember(Base): __tablename__ = 'users_groups_members' __table_args__ = {'useexisting':True} @@ -195,7 +240,7 @@ fork = relationship('Repository', remote_side=repo_id) group = relationship('Group') repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id') - users_group_to_perm = relationship('UsersGroupToPerm', cascade='all') + users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all') stats = relationship('Statistics', cascade='all', uselist=False) followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all') @@ -285,6 +330,10 @@ return "<%s('%s:%s')>" % (self.__class__.__name__, self.permission_id, self.permission_name) + @classmethod + def get_by_key(cls, key): + return Session.query(cls).filter(cls.permission_name == key).scalar() + class RepoToPerm(Base): __tablename__ = 'repo_to_perm' __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True}) @@ -307,9 +356,43 @@ user = relationship('User') permission = relationship('Permission') + @classmethod + def has_perm(cls, user_id, perm): + if not isinstance(perm, Permission): + raise Exception('perm needs to be an instance of Permission class') -class UsersGroupToPerm(Base): - __tablename__ = 'users_group_to_perm' + return Session.query(cls).filter(cls.user_id == user_id)\ + .filter(cls.permission == perm).scalar() is not None + + @classmethod + def grant_perm(cls, user_id, perm): + if not isinstance(perm, Permission): + raise Exception('perm needs to be an instance of Permission class') + + new = cls() + new.user_id = user_id + new.permission = perm + try: + Session.add(new) + Session.commit() + except: + Session.rollback() + + + @classmethod + def revoke_perm(cls, user_id, perm): + if not isinstance(perm, Permission): + raise Exception('perm needs to be an instance of Permission class') + + try: + Session.query(cls).filter(cls.user_id == user_id)\ + .filter(cls.permission == perm).delete() + Session.commit() + except: + Session.rollback() + +class UsersGroupRepoToPerm(Base): + __tablename__ = 'users_group_repo_to_perm' __table_args__ = (UniqueConstraint('users_group_id', 'permission_id'), {'useexisting':True}) users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) @@ -320,6 +403,55 @@ permission = relationship('Permission') repository = relationship('Repository') + +class UsersGroupToPerm(Base): + __tablename__ = 'users_group_to_perm' + users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) + permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) + + users_group = relationship('UsersGroup') + permission = relationship('Permission') + + + @classmethod + def has_perm(cls, users_group_id, perm): + if not isinstance(perm, Permission): + raise Exception('perm needs to be an instance of Permission class') + + return Session.query(cls).filter(cls.users_group_id == + users_group_id)\ + .filter(cls.permission == perm)\ + .scalar() is not None + + @classmethod + def grant_perm(cls, users_group_id, perm): + if not isinstance(perm, Permission): + raise Exception('perm needs to be an instance of Permission class') + + new = cls() + new.users_group_id = users_group_id + new.permission = perm + try: + Session.add(new) + Session.commit() + except: + Session.rollback() + + + @classmethod + def revoke_perm(cls, users_group_id, perm): + if not isinstance(perm, Permission): + raise Exception('perm needs to be an instance of Permission class') + + try: + Session.query(cls).filter(cls.users_group_id == users_group_id)\ + .filter(cls.permission == perm).delete() + Session.commit() + except: + Session.rollback() + + class GroupToPerm(Base): __tablename__ = 'group_to_perm' __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'useexisting':True}) @@ -355,12 +487,19 @@ user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) + follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') follows_repository = relationship('Repository', order_by='Repository.repo_name') + + + @classmethod + def get_repo_followers(cls, repo_id): + return Session.query(cls).filter(cls.follows_repo_id == repo_id) + class CacheInvalidation(Base): __tablename__ = 'cache_invalidation' __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
--- a/rhodecode/model/forms.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/forms.py Tue Apr 26 14:03:00 2011 +0200 @@ -37,7 +37,6 @@ from rhodecode.model import meta from rhodecode.model.user import UserModel from rhodecode.model.repo import RepoModel -from rhodecode.model.users_group import UsersGroupModel from rhodecode.model.db import User, UsersGroup from rhodecode import BACKENDS @@ -47,9 +46,9 @@ class State_obj(object): _ = staticmethod(_) -#=============================================================================== +#============================================================================== # VALIDATORS -#=============================================================================== +#============================================================================== class ValidAuthToken(formencode.validators.FancyValidator): messages = {'invalid_token':_('Token mismatch')} @@ -73,23 +72,19 @@ if old_un != value or not edit: if UserModel().get_by_username(value, cache=False, case_insensitive=True): - raise formencode.Invalid(_('This username already exists') , - value, state) - + raise formencode.Invalid(_('This username already ' + 'exists') , value, state) if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None: raise formencode.Invalid(_('Username may only contain ' - 'alphanumeric characters underscores, ' - 'periods or dashes and must begin with ' - 'alphanumeric character'), - value, state) - - + 'alphanumeric characters ' + 'underscores, periods or dashes ' + 'and must begin with alphanumeric ' + 'character'), value, state) return _ValidUsername - def ValidUsersGroup(edit, old_data): class _ValidUsersGroup(formencode.validators.FancyValidator): @@ -100,22 +95,23 @@ #check if group is unique old_ugname = None if edit: - old_ugname = UsersGroupModel()\ - .get(old_data.get('users_group_id')).users_group_name + old_ugname = UsersGroup.get( + old_data.get('users_group_id')).users_group_name if old_ugname != value or not edit: - if UsersGroupModel().get_by_groupname(value, cache=False, + if UsersGroup.get_by_group_name(value, cache=False, case_insensitive=True): - raise formencode.Invalid(_('This users group already exists') , - value, state) + raise formencode.Invalid(_('This users group ' + 'already exists') , value, + state) if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None: raise formencode.Invalid(_('Group name may only contain ' - 'alphanumeric characters underscores, ' - 'periods or dashes and must begin with ' - 'alphanumeric character'), - value, state) + 'alphanumeric characters ' + 'underscores, periods or dashes ' + 'and must begin with alphanumeric ' + 'character'), value, state) return _ValidUsersGroup @@ -226,13 +222,40 @@ return _ValidRepoName +def ValidCloneUri(): + from mercurial.httprepo import httprepository, httpsrepository + from rhodecode.lib.utils import make_ui + + class _ValidCloneUri(formencode.validators.FancyValidator): + def to_python(self, value, state): + if not value: + pass + elif value.startswith('https'): + try: + httpsrepository(make_ui('db'), value).capabilities() + except: + raise formencode.Invalid(_('invalid clone url'), value, + state) + elif value.startswith('http'): + try: + httprepository(make_ui('db'), value).capabilities() + except: + raise formencode.Invalid(_('invalid clone url'), value, + state) + else: + raise formencode.Invalid(_('Invalid clone url, provide a ' + 'valid clone http\s url'), value, + state) + + return _ValidCloneUri + def ValidForkType(old_data): class _ValidForkType(formencode.validators.FancyValidator): def to_python(self, value, state): if old_data['repo_type'] != value: - raise formencode.Invalid(_('Fork have to be the same type as original'), - value, state) + raise formencode.Invalid(_('Fork have to be the same ' + 'type as original'), value, state) return value return _ValidForkType @@ -457,7 +480,8 @@ filter_extra_fields = False repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data)) - clone_uri = UnicodeString(strip=True, min=1, not_empty=False) + clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False), + ValidCloneUri()()) repo_group = OneOf(repo_groups, hideList=True) repo_type = OneOf(supported_backends) description = UnicodeString(strip=True, min=1, not_empty=True)
--- a/rhodecode/model/meta.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/meta.py Tue Apr 26 14:03:00 2011 +0200 @@ -19,6 +19,7 @@ ) ) + class BaseModel(object): """Base Model for all classess
--- a/rhodecode/model/permission.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/permission.py Tue Apr 26 14:03:00 2011 +0200 @@ -66,8 +66,10 @@ def update(self, form_result): perm_user = self.sa.query(User)\ - .filter(User.username == form_result['perm_user_name']).scalar() - u2p = self.sa.query(UserToPerm).filter(UserToPerm.user == perm_user).all() + .filter(User.username == + form_result['perm_user_name']).scalar() + u2p = self.sa.query(UserToPerm).filter(UserToPerm.user == + perm_user).all() if len(u2p) != 3: raise Exception('Defined: %s should be 3 permissions for default' ' user. This should not happen please verify' @@ -104,7 +106,6 @@ perm_user.active = bool(form_result['anonymous']) self.sa.add(perm_user) - self.sa.commit() except (DatabaseError,): log.error(traceback.format_exc())
--- a/rhodecode/model/repo.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/repo.py Tue Apr 26 14:03:00 2011 +0200 @@ -36,13 +36,12 @@ from rhodecode.model import BaseModel from rhodecode.model.caching_query import FromCache from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \ - Statistics, UsersGroup, UsersGroupToPerm, RhodeCodeUi + Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi from rhodecode.model.user import UserModel -from rhodecode.model.users_group import UsersGroupMember, UsersGroupModel - log = logging.getLogger(__name__) + class RepoModel(BaseModel): @LazyProperty @@ -62,7 +61,6 @@ "get_repo_%s" % repo_id)) return repo.scalar() - def get_by_repo_name(self, repo_name, cache=False): repo = self.sa.query(Repository)\ .filter(Repository.repo_name == repo_name) @@ -72,7 +70,6 @@ "get_repo_%s" % repo_name)) return repo.scalar() - def get_full(self, repo_name, cache=False, invalidate=False): repo = self.sa.query(Repository)\ .options(joinedload(Repository.fork))\ @@ -95,7 +92,6 @@ make_transient(attr) return ret - def get_users_js(self): users = self.sa.query(User).filter(User.active == True).all() @@ -105,7 +101,6 @@ for u in users]) return users_array - def get_users_groups_js(self): users_groups = self.sa.query(UsersGroup)\ .filter(UsersGroup.users_group_active == True).all() @@ -122,29 +117,30 @@ try: cur_repo = self.get_by_repo_name(repo_name, cache=False) user_model = UserModel(self.sa) - users_group_model = UsersGroupModel(self.sa) #update permissions for member, perm, member_type in form_data['perms_updates']: if member_type == 'user': r2p = self.sa.query(RepoToPerm)\ - .filter(RepoToPerm.user == user_model.get_by_username(member))\ + .filter(RepoToPerm.user == user_model. + get_by_username(member))\ .filter(RepoToPerm.repository == cur_repo)\ .one() r2p.permission = self.sa.query(Permission)\ - .filter(Permission.permission_name == perm)\ - .scalar() + .filter(Permission.permission_name == + perm).scalar() self.sa.add(r2p) else: - g2p = self.sa.query(UsersGroupToPerm)\ - .filter(UsersGroupToPerm.users_group == users_group_model.get_by_groupname(member))\ - .filter(UsersGroupToPerm.repository == cur_repo)\ - .one() + g2p = self.sa.query(UsersGroupRepoToPerm)\ + .filter(UsersGroupRepoToPerm.users_group == + UsersGroup.get_by_group_name(member))\ + .filter(UsersGroupRepoToPerm.repository == + cur_repo).one() g2p.permission = self.sa.query(Permission)\ - .filter(Permission.permission_name == perm)\ - .scalar() + .filter(Permission.permission_name == + perm).scalar() self.sa.add(g2p) #set new permissions @@ -155,17 +151,19 @@ r2p.user = user_model.get_by_username(member) r2p.permission = self.sa.query(Permission)\ - .filter(Permission.permission_name == perm)\ - .scalar() + .filter(Permission. + permission_name == perm)\ + .scalar() self.sa.add(r2p) else: - g2p = UsersGroupToPerm() + g2p = UsersGroupRepoToPerm() g2p.repository = cur_repo - g2p.users_group = users_group_model.get_by_groupname(member) + g2p.users_group = UsersGroup.get_by_group_name(member) g2p.permission = self.sa.query(Permission)\ - .filter(Permission.permission_name == perm)\ - .scalar() + .filter(Permission. + permission_name == perm)\ + .scalar() self.sa.add(g2p) #update current repo @@ -276,10 +274,10 @@ def delete_perm_users_group(self, form_data, repo_name): try: - self.sa.query(UsersGroupToPerm)\ - .filter(UsersGroupToPerm.repository \ + self.sa.query(UsersGroupRepoToPerm)\ + .filter(UsersGroupRepoToPerm.repository \ == self.get_by_repo_name(repo_name))\ - .filter(UsersGroupToPerm.users_group_id \ + .filter(UsersGroupRepoToPerm.users_group_id \ == form_data['users_group_id']).delete() self.sa.commit() except: @@ -298,7 +296,6 @@ self.sa.rollback() raise - def __create_repo(self, repo_name, alias, clone_uri=False): """ makes repository on filesystem
--- a/rhodecode/model/scm.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/scm.py Tue Apr 26 14:03:00 2011 +0200 @@ -140,7 +140,9 @@ repo, dbrepo = r_dbr if repo is None or dbrepo is None: - log.error('Repository %s looks somehow corrupted', r_name) + log.error('Repository "%s" looks somehow corrupted ' + 'fs-repo:%s,db-repo:%s both values should be ' + 'present', r_name, repo, dbrepo) continue last_change = repo.last_change tip = h.get_changeset_safe(repo, 'tip') @@ -342,22 +344,18 @@ return f is not None def get_followers(self, repo_id): - if isinstance(repo_id, int): - return self.sa.query(UserFollowing)\ - .filter(UserFollowing.follows_repo_id == repo_id).count() - else: - return self.sa.query(UserFollowing)\ - .filter(UserFollowing.follows_repository \ - == RepoModel().get_by_repo_name(repo_id)).count() + if not isinstance(repo_id, int): + repo_id = getattr(Repository.by_repo_name(repo_id), 'repo_id') + + return self.sa.query(UserFollowing)\ + .filter(UserFollowing.follows_repo_id == repo_id).count() def get_forks(self, repo_id): - if isinstance(repo_id, int): - return self.sa.query(Repository)\ + if not isinstance(repo_id, int): + repo_id = getattr(Repository.by_repo_name(repo_id), 'repo_id') + + return self.sa.query(Repository)\ .filter(Repository.fork_id == repo_id).count() - else: - return self.sa.query(Repository)\ - .filter(Repository.fork \ - == RepoModel().get_by_repo_name(repo_id)).count() def pull_changes(self, repo_name, username): repo, dbrepo = self.get(repo_name, retval='all')
--- a/rhodecode/model/user.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/user.py Tue Apr 26 14:03:00 2011 +0200 @@ -31,18 +31,21 @@ from rhodecode.model import BaseModel from rhodecode.model.caching_query import FromCache from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \ - UserToPerm, UsersGroupToPerm, UsersGroupMember -from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException + UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember +from rhodecode.lib.exceptions import DefaultUserException, \ + UserOwnsReposException from sqlalchemy.exc import DatabaseError from rhodecode.lib import generate_api_key +from sqlalchemy.orm import joinedload log = logging.getLogger(__name__) -PERM_WEIGHTS = {'repository.none':0, - 'repository.read':1, - 'repository.write':3, - 'repository.admin':3} +PERM_WEIGHTS = {'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 3} + class UserModel(BaseModel): @@ -53,7 +56,6 @@ "get_user_%s" % user_id)) return user.get(user_id) - def get_by_username(self, username, cache=False, case_insensitive=False): if case_insensitive: @@ -66,7 +68,6 @@ "get_user_%s" % username)) return user.scalar() - def get_by_api_key(self, api_key, cache=False): user = self.sa.query(User)\ @@ -104,7 +105,8 @@ if self.get_by_username(username, case_insensitive=True) is None: try: new_user = User() - new_user.username = username.lower() # add ldap account always lowercase + # add ldap account always lowercase + new_user.username = username.lower() new_user.password = get_crypt_password(password) new_user.api_key = generate_api_key(username) new_user.email = attrs['email'] @@ -113,7 +115,6 @@ new_user.name = attrs['name'] new_user.lastname = attrs['lastname'] - self.sa.add(new_user) self.sa.commit() return True @@ -216,7 +217,6 @@ from rhodecode.lib.celerylib import tasks, run_task run_task(tasks.reset_user_password, data['email']) - def fill_data(self, auth_user, user_id=None, api_key=None): """ Fetches auth_user by user_id,or api_key if present. @@ -248,11 +248,11 @@ return auth_user - def fill_perms(self, user): - """Fills user permission attribute with permissions taken from database + """ + Fills user permission attribute with permissions taken from database works for permissions given for repositories, and for permissions that - as part of beeing group member + are granted to groups :param user: user instance to fill his perms """ @@ -260,83 +260,124 @@ user.permissions['repositories'] = {} user.permissions['global'] = set() - #=========================================================================== + #====================================================================== # fetch default permissions - #=========================================================================== + #====================================================================== default_user = self.get_by_username('default', cache=True) default_perms = self.sa.query(RepoToPerm, Repository, Permission)\ - .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\ - .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\ + .join((Repository, RepoToPerm.repository_id == + Repository.repo_id))\ + .join((Permission, RepoToPerm.permission_id == + Permission.permission_id))\ .filter(RepoToPerm.user == default_user).all() if user.is_admin: - #======================================================================= + #================================================================== # #admin have all default rights set to admin - #======================================================================= + #================================================================== user.permissions['global'].add('hg.admin') for perm in default_perms: p = 'repository.admin' - user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p + user.permissions['repositories'][perm.RepoToPerm. + repository.repo_name] = p else: - #======================================================================= + #================================================================== # set default permissions - #======================================================================= + #================================================================== + uid = user.user_id #default global default_global_perms = self.sa.query(UserToPerm)\ - .filter(UserToPerm.user == self.sa.query(User)\ - .filter(User.username == 'default').one()) + .filter(UserToPerm.user == default_user) for perm in default_global_perms: user.permissions['global'].add(perm.permission.permission_name) #default for repositories for perm in default_perms: - if perm.Repository.private and not perm.Repository.user_id == user.user_id: + if perm.Repository.private and not (perm.Repository.user_id == + uid): #diself.sable defaults for private repos, p = 'repository.none' - elif perm.Repository.user_id == user.user_id: + elif perm.Repository.user_id == uid: #set admin if owner p = 'repository.admin' else: p = perm.Permission.permission_name - user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p + user.permissions['repositories'][perm.RepoToPerm. + repository.repo_name] = p - #======================================================================= + #================================================================== # overwrite default with user permissions if any - #======================================================================= - user_perms = self.sa.query(RepoToPerm, Permission, Repository)\ - .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\ - .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\ - .filter(RepoToPerm.user_id == user.user_id).all() + #================================================================== + + #user global + user_perms = self.sa.query(UserToPerm)\ + .options(joinedload(UserToPerm.permission))\ + .filter(UserToPerm.user_id == uid).all() for perm in user_perms: - if perm.Repository.user_id == user.user_id:#set admin if owner + user.permissions['global'].add(perm.permission. + permission_name) + + #user repositories + user_repo_perms = self.sa.query(RepoToPerm, Permission, + Repository)\ + .join((Repository, RepoToPerm.repository_id == + Repository.repo_id))\ + .join((Permission, RepoToPerm.permission_id == + Permission.permission_id))\ + .filter(RepoToPerm.user_id == uid).all() + + for perm in user_repo_perms: + # set admin if owner + if perm.Repository.user_id == uid: p = 'repository.admin' else: p = perm.Permission.permission_name - user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p + user.permissions['repositories'][perm.RepoToPerm. + repository.repo_name] = p - - #======================================================================= + #================================================================== # check if user is part of groups for this repository and fill in # (or replace with higher) permissions - #======================================================================= - user_perms_from_users_groups = self.sa.query(UsersGroupToPerm, Permission, Repository,)\ - .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\ - .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\ - .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\ - .filter(UsersGroupMember.user_id == user.user_id).all() + #================================================================== + + #users group global + user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\ + .options(joinedload(UsersGroupToPerm.permission))\ + .join((UsersGroupMember, UsersGroupToPerm.users_group_id == + UsersGroupMember.users_group_id))\ + .filter(UsersGroupMember.user_id == uid).all() for perm in user_perms_from_users_groups: + user.permissions['global'].add(perm.permission.permission_name) + + #users group repositories + user_repo_perms_from_users_groups = self.sa.query( + UsersGroupRepoToPerm, + Permission, Repository,)\ + .join((Repository, UsersGroupRepoToPerm.repository_id == + Repository.repo_id))\ + .join((Permission, UsersGroupRepoToPerm.permission_id == + Permission.permission_id))\ + .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == + UsersGroupMember.users_group_id))\ + .filter(UsersGroupMember.user_id == uid).all() + + for perm in user_repo_perms_from_users_groups: p = perm.Permission.permission_name - cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] - #overwrite permission only if it's greater than permission given from other sources + cur_perm = user.permissions['repositories'][perm. + UsersGroupRepoToPerm. + repository.repo_name] + #overwrite permission only if it's greater than permission + # given from other sources if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]: - user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p + user.permissions['repositories'][perm.UsersGroupRepoToPerm. + repository.repo_name] = p return user
--- a/rhodecode/model/users_group.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/model/users_group.py Tue Apr 26 14:03:00 2011 +0200 @@ -32,8 +32,6 @@ from rhodecode.model.caching_query import FromCache from rhodecode.model.db import UsersGroup, UsersGroupMember -from sqlalchemy.exc import DatabaseError - log = logging.getLogger(__name__) @@ -43,24 +41,9 @@ users_group = self.sa.query(UsersGroup) if cache: users_group = users_group.options(FromCache("sql_cache_short", - "get_users_group_%s" % users_group_id)) + "get_users_group_%s" % users_group_id)) return users_group.get(users_group_id) - - def get_by_groupname(self, users_group_name, cache=False, - case_insensitive=False): - - if case_insensitive: - user = self.sa.query(UsersGroup)\ - .filter(UsersGroup.users_group_name.ilike(users_group_name)) - else: - user = self.sa.query(UsersGroup)\ - .filter(UsersGroup.users_group_name == users_group_name) - if cache: - user = user.options(FromCache("sql_cache_short", - "get_user_%s" % users_group_name)) - return user.scalar() - def create(self, form_data): try: new_users_group = UsersGroup() @@ -86,8 +69,9 @@ members_list = [] if v: for u_id in set(v): - members_list.append(UsersGroupMember(users_group_id, - u_id)) + members_list.append(UsersGroupMember( + users_group_id, + u_id)) setattr(users_group, 'members', members_list) setattr(users_group, k, v)
--- a/rhodecode/public/css/style.css Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/public/css/style.css Tue Apr 26 14:03:00 2011 +0200 @@ -389,6 +389,12 @@ overflow-x:hidden; overflow-y:auto; } +#header #header-inner #quick ul.repo_switcher li.qfilter_rs { +float:none; +margin:0; +border-bottom:2px solid #003367; +} + #header #header-inner #quick .repo_switcher_type{ position:absolute; @@ -829,7 +835,7 @@ } #content div.box div.form div.fields div.field div.label { -left:80px; +left:70px; width:auto; position:absolute; margin:0; @@ -1546,6 +1552,24 @@ font-weight: bold; } +.cs_files .node{ +float: left; +} +.cs_files .changes{ +float: right; +} +.cs_files .changes .added{ +background-color: #BBFFBB; +float: left; +text-align: center; +font-size: 90%; +} +.cs_files .changes .deleted{ +background-color: #FF8888; +float: left; +text-align: center; +font-size: 90%; +} .cs_files .cs_added { background:url("../images/icons/page_white_add.png") no-repeat scroll 3px; height:16px;
--- a/rhodecode/templates/admin/users/user_edit.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/admin/users/user_edit.html Tue Apr 26 14:03:00 2011 +0200 @@ -24,7 +24,7 @@ ${self.breadcrumbs()} </div> <!-- end box / title --> - ${h.form(url('user', id=c.user.user_id),method='put')} + ${h.form(url('update_user', id=c.user.user_id),method='put')} <div class="form"> <div class="field"> <div class="gravatar_box"> @@ -126,7 +126,7 @@ <div class="title"> <h5>${_('Permissions')}</h5> </div> - ${h.form(url('user', id=c.user.user_id),method='put')} + ${h.form(url('user_perm', id=c.user.user_id),method='put')} <div class="form"> <!-- fields --> <div class="fields"> @@ -135,7 +135,7 @@ <label for="">${_('Create repositories')}:</label> </div> <div class="checkboxes"> - ${h.checkbox('create',value=True)} + ${h.checkbox('create_repo_perm',value=True)} </div> </div> <div class="buttons">
--- a/rhodecode/templates/admin/users/users.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/admin/users/users.html Tue Apr 26 14:03:00 2011 +0200 @@ -51,7 +51,7 @@ <td>${h.bool2icon(user.admin)}</td> <td>${h.bool2icon(bool(user.ldap_dn))}</td> <td> - ${h.form(url('user', id=user.user_id),method='delete')} + ${h.form(url('delete_user', id=user.user_id),method='delete')} ${h.submit('remove_','delete',id="remove_user_%s" % user.user_id, class_="delete_icon action_button",onclick="return confirm('Confirm to delete this user');")} ${h.end_form()}
--- a/rhodecode/templates/admin/users_groups/users_group_edit.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/admin/users_groups/users_group_edit.html Tue Apr 26 14:03:00 2011 +0200 @@ -247,7 +247,7 @@ <div class="title"> <h5>${_('Permissions')}</h5> </div> - ${h.form(url('user', id=''),method='put')} + ${h.form(url('users_group_perm', id=c.users_group.users_group_id), method='put')} <div class="form"> <!-- fields --> <div class="fields"> @@ -256,7 +256,7 @@ <label for="">${_('Create repositories')}:</label> </div> <div class="checkboxes"> - ${h.checkbox('create',value=True)} + ${h.checkbox('create_repo_perm',value=True)} </div> </div> <div class="buttons">
--- a/rhodecode/templates/base/base.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/base/base.html Tue Apr 26 14:03:00 2011 +0200 @@ -121,12 +121,55 @@ </ul> <script type="text/javascript"> YUE.on('repo_switcher','mouseover',function(){ + function qfilter(){ + var S = YAHOO.util.Selector; + + var q_filter = YUD.get('q_filter_rs'); + var F = YAHOO.namespace('q_filter_rs'); + + YUE.on(q_filter,'click',function(){ + q_filter.value = ''; + }); + + F.filterTimeout = null; + + F.updateFilter = function() { + // Reset timeout + F.filterTimeout = null; + + var obsolete = []; + var nodes = S.query('ul#repo_switcher_list li a.repo_name'); + var req = YUD.get('q_filter_rs').value; + for (n in nodes){ + YUD.setStyle(nodes[n].parentNode,'display','') + } + if (req){ + for (n in nodes){ + console.log(n); + if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) { + obsolete.push(nodes[n]); + } + } + if(obsolete){ + for (n in obsolete){ + YUD.setStyle(obsolete[n].parentNode,'display','none'); + } + } + } + } + + YUE.on(q_filter,'keyup',function(e){ + clearTimeout(F.filterTimeout); + setTimeout(F.updateFilter,600); + }); + } var loaded = YUD.hasClass('repo_switcher','loaded'); if(!loaded){ YUD.addClass('repo_switcher','loaded'); YAHOO.util.Connect.asyncRequest('GET',"${h.url('repo_switcher')}",{ success:function(o){ YUD.get('repo_switcher_list').innerHTML = o.responseText; + qfilter(); }, failure:function(o){ YUD.removeClass('repo_switcher','loaded'); @@ -247,7 +290,7 @@ </li> <li> - <a title="${_('Followers')}" href="#"> + <a title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}"> <span class="icon_short"> <img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" /> </span>
--- a/rhodecode/templates/changeset/changeset.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/changeset/changeset.html Tue Apr 26 14:03:00 2011 +0200 @@ -86,10 +86,16 @@ </span> </div> </div> - <span style="font-size:1.1em;font-weight: bold">${_('Files affected (%s)' % len(c.changeset.affected_files))}</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)} + </span> <div class="cs_files"> - %for change,filenode,diff,cs1,cs2 in c.changes: - <div class="cs_${change}">${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.repo_name_slug('C%s' % h.safe_unicode(filenode.path))))}</div> + %for change,filenode,diff,cs1,cs2,stat in c.changes: + <div class="cs_${change}"> + <div class="node">${h.link_to(h.safe_unicode(filenode.path), + h.url.current(anchor=h.repo_name_slug('C%s' % h.safe_unicode(filenode.path))))}</div> + <div class="changes">${h.fancy_file_stats(stat)}</div> + </div> %endfor % if c.cut_off: ${_('Changeset was to big and was cut off...')} @@ -99,7 +105,7 @@ </div> - %for change,filenode,diff,cs1,cs2 in c.changes: + %for change,filenode,diff,cs1,cs2,stat in c.changes: %if change !='removed': <div style="clear:both;height:10px"></div> <div class="diffblock">
--- a/rhodecode/templates/changeset/changeset_range.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/changeset/changeset_range.html Tue Apr 26 14:03:00 2011 +0200 @@ -53,7 +53,7 @@ <div class="cs_files"> %for cs in c.cs_ranges: <div class="cur_cs">r${cs}</div> - %for change,filenode,diff,cs1,cs2 in c.changes[cs.raw_id]: + %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.repo_name_slug('C%s-%s' % (cs.short_id,h.safe_unicode(filenode.path)))))}</div> %endfor %endfor @@ -62,7 +62,7 @@ </div> %for cs in c.cs_ranges: - %for change,filenode,diff,cs1,cs2 in c.changes[cs.raw_id]: + %for change,filenode,diff,cs1,cs2,st in c.changes[cs.raw_id]: %if change !='removed': <div style="clear:both;height:10px"></div> <div class="diffblock">
--- a/rhodecode/templates/files/file_diff.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/files/file_diff.html Tue Apr 26 14:03:00 2011 +0200 @@ -38,6 +38,9 @@ <div class="code-body"> %if c.no_changes: ${_('No changes')} + %elif c.big_diff: + ${_('Diff is to big to display')} ${h.link_to(_('raw diff'), + h.url.current(diff2=c.changeset_2.raw_id,diff1=c.changeset_1.raw_id,diff='raw'))} %else: ${c.cur_diff|n} %endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rhodecode/templates/followers/followers.html Tue Apr 26 14:03:00 2011 +0200 @@ -0,0 +1,32 @@ +## -*- coding: utf-8 -*- +<%inherit file="/base/base.html"/> + +<%def name="title()"> + ${c.repo_name} ${_('Followers')} - ${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))} + » + ${_('followers')} +</%def> + +<%def name="page_nav()"> + ${self.menu('followers')} +</%def> +<%def name="main()"> +<div class="box"> + <!-- box / title --> + <div class="title"> + ${self.breadcrumbs()} + </div> + <!-- end box / title --> + <div class="table"> + <div id="followers"> + ${c.followers_data} + </div> + </div> +</div> +</%def> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rhodecode/templates/followers/followers_data.html Tue Apr 26 14:03:00 2011 +0200 @@ -0,0 +1,36 @@ +## -*- coding: utf-8 -*- + +% for f in c.followers_pager: + <div> + <div class="follower_user"> + <div class="gravatar"> + <img alt="gravatar" src="${h.gravatar_url(f.user.email,24)}"/> + </div> + <span style="font-size: 20px"> <b>${f.user.username}</b> (${f.user.name} ${f.user.lastname})</span> + </div> + <div style="clear:both;padding-top: 10px"></div> + <div class="follower_date">${_('Started following')} - + <span class="tooltip" title="${f.follows_from}"> ${h.age(f.follows_from)}</span></div> + <div style="border-bottom: 1px solid #DDD;margin:10px 0px 10px 0px"></div> + </div> +% endfor + +<div class="pagination-wh pagination-left"> +<script type="text/javascript"> + var data_div = 'followers'; + YAHOO.util.Event.onDOMReady(function(){ + YAHOO.util.Event.addListener( + YUD.getElementsByClassName('pager_link'),"click", + function(){ + YAHOO.util.Dom.setStyle(data_div,'opacity','0.3'); + }); + }); +</script> + +${c.followers_pager.pager('$link_previous ~2~ $link_next', +onclick="""YAHOO.util.Connect.asyncRequest('GET','$partial_url',{ +success:function(o){YAHOO.util.Dom.get(data_div).innerHTML=o.responseText; +YUE.on(YAHOO.util.Dom.getElementsByClassName('pager_link'),"click",function(){ + YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');}); +YAHOO.util.Dom.setStyle(data_div,'opacity','1');}},null); return false;""")} +</div> \ No newline at end of file
--- a/rhodecode/templates/repo_switcher_list.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/repo_switcher_list.html Tue Apr 26 14:03:00 2011 +0200 @@ -1,15 +1,23 @@ -## -*- coding: utf-8 -*- +## -*- coding: utf-8 -*- + +<li class="qfilter_rs"> +<input type="text" +style="border:0" +value="quick filter..." +name="filter" size="15" id="q_filter_rs" /> +</li> + %for repo in c.repos_list: %if repo['dbrepo']['private']: <li> <img src="${h.url("/images/icons/lock.png")}" alt="${_('Private repository')}" class="repo_switcher_type"/> - ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="%s" % repo['dbrepo']['repo_type'])} + ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name %s" % repo['dbrepo']['repo_type'])} </li> %else: <li> <img src="${h.url("/images/icons/lock_open.png")}" alt="${_('Public repository')}" class="repo_switcher_type" /> - ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="%s" % repo['dbrepo']['repo_type'])} + ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name %s" % repo['dbrepo']['repo_type'])} </li> %endif %endfor \ No newline at end of file
--- a/rhodecode/templates/summary/summary.html Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/templates/summary/summary.html Tue Apr 26 14:03:00 2011 +0200 @@ -130,7 +130,7 @@ <label>${_('Clone url')}:</label> </div> <div class="input-short"> - <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/> + <input type="text" id="clone_url" readonly="readonly" value="${c.rhodecode_repo.alias} clone ${c.clone_repo_url}" size="70"/> </div> </div>
--- a/rhodecode/tests/test_hg_operations.py Tue Apr 26 14:02:53 2011 +0200 +++ b/rhodecode/tests/test_hg_operations.py Tue Apr 26 14:03:00 2011 +0200 @@ -14,6 +14,7 @@ import shutil import logging from os.path import join as jn +from os.path import dirname as dn from tempfile import _RandomNameSequence from subprocess import Popen, PIPE @@ -31,7 +32,8 @@ from rhodecode.tests import TESTS_TMP_PATH, NEW_HG_REPO, HG_REPO from rhodecode.config.environment import load_environment -conf = appconfig('config:development.ini', relative_to='./../../') +rel_path = dn(dn(dn(os.path.abspath(__file__)))) +conf = appconfig('config:development.ini', relative_to=rel_path) load_environment(conf.global_conf, conf.local_conf) add_cache(conf)