"""
Routes configuration
The more specific and detailed routes should be defined first so they
may take precedent over the more generic routes. For more information
refer to the routes manual at http://routes.groovie.org/docs/
from __future__ import with_statement
from routes import Mapper
# prefix for non repository related links needs to be prefixed with `/`
ADMIN_PREFIX = '/_admin'
def make_map(config):
"""Create, configure and return the routes Mapper"""
rmap = Mapper(directory=config['pylons.paths']['controllers'],
always_scan=config['debug'])
rmap.minimization = False
rmap.explicit = False
from rhodecode.lib.utils import is_valid_repo
from rhodecode.lib.utils import is_valid_repos_group
def check_repo(environ, match_dict):
check for valid repository for proper 404 handling
:param environ:
:param match_dict:
from rhodecode.model.db import Repository
repo_name = match_dict.get('repo_name')
try:
by_id = repo_name.split('_')
if len(by_id) == 2 and by_id[1].isdigit():
if len(by_id) == 2 and by_id[1].isdigit() and by_id[0] == '':
repo_name = Repository.get(by_id[1]).repo_name
match_dict['repo_name'] = repo_name
except:
pass
return is_valid_repo(repo_name, config['base_path'])
def check_group(environ, match_dict):
check for valid repositories group for proper 404 handling
repos_group_name = match_dict.get('group_name')
return is_valid_repos_group(repos_group_name, config['base_path'])
def check_int(environ, match_dict):
return match_dict.get('id').isdigit()
# The ErrorController route (handles 404/500 error pages); it should
# likely stay at the top, ensuring it can always be resolved
rmap.connect('/error/{action}', controller='error')
rmap.connect('/error/{action}/{id}', controller='error')
#==========================================================================
# CUSTOM ROUTES HERE
#MAIN PAGE
rmap.connect('home', '/', controller='home', action='index')
rmap.connect('repo_switcher', '/repos', controller='home',
action='repo_switcher')
rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*?}',
controller='home', action='branch_tag_switcher')
rmap.connect('bugtracker',
"http://bitbucket.org/marcinkuzminski/rhodecode/issues",
_static=True)
rmap.connect('rst_help',
"http://docutils.sourceforge.net/docs/user/rst/quickref.html",
rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True)
#ADMIN REPOSITORY REST ROUTES
with rmap.submapper(path_prefix=ADMIN_PREFIX,
controller='admin/repos') as m:
m.connect("repos", "/repos",
action="create", conditions=dict(method=["POST"]))
action="index", conditions=dict(method=["GET"]))
m.connect("formatted_repos", "/repos.{format}",
action="index",
conditions=dict(method=["GET"]))
m.connect("new_repo", "/repos/new",
action="new", conditions=dict(method=["GET"]))
m.connect("formatted_new_repo", "/repos/new.{format}",
m.connect("/repos/{repo_name:.*?}",
action="update", conditions=dict(method=["PUT"],
function=check_repo))
action="delete", conditions=dict(method=["DELETE"],
m.connect("edit_repo", "/repos/{repo_name:.*?}/edit",
action="edit", conditions=dict(method=["GET"],
m.connect("formatted_edit_repo", "/repos/{repo_name:.*?}.{format}/edit",
m.connect("repo", "/repos/{repo_name:.*?}",
action="show", conditions=dict(method=["GET"],
m.connect("formatted_repo", "/repos/{repo_name:.*?}.{format}",
#ajax delete repo perm user
m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*?}",
action="delete_perm_user",
conditions=dict(method=["DELETE"], function=check_repo))
#ajax delete repo perm users_group
m.connect('delete_repo_users_group',
"/repos_delete_users_group/{repo_name:.*?}",
action="delete_perm_users_group",
#settings actions
m.connect('repo_stats', "/repos_stats/{repo_name:.*?}",
action="repo_stats", conditions=dict(method=["DELETE"],
m.connect('repo_cache', "/repos_cache/{repo_name:.*?}",
action="repo_cache", conditions=dict(method=["DELETE"],
m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*?}",
action="repo_public_journal", conditions=dict(method=["PUT"],
m.connect('repo_pull', "/repo_pull/{repo_name:.*?}",
action="repo_pull", conditions=dict(method=["PUT"],
m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*?}",
action="repo_as_fork", conditions=dict(method=["PUT"],
m.connect('repo_locking', "/repo_locking/{repo_name:.*?}",
action="repo_locking", conditions=dict(method=["PUT"],
controller='admin/repos_groups') as m:
m.connect("repos_groups", "/repos_groups",
m.connect("formatted_repos_groups", "/repos_groups.{format}",
m.connect("new_repos_group", "/repos_groups/new",
m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
m.connect("update_repos_group", "/repos_groups/{id}",
function=check_int))
m.connect("delete_repos_group", "/repos_groups/{id}",
m.connect("edit_repos_group", "/repos_groups/{id:.*?}/edit",
action="edit", conditions=dict(method=["GET"],))
m.connect("formatted_edit_repos_group",
"/repos_groups/{id}.{format}/edit",
m.connect("repos_group", "/repos_groups/{id}",
m.connect("formatted_repos_group", "/repos_groups/{id}.{format}",
# ajax delete repos group perm user
m.connect('delete_repos_group_user_perm',
"/delete_repos_group_user_perm/{group_name:.*}",
action="delete_repos_group_user_perm",
conditions=dict(method=["DELETE"], function=check_group))
# ajax delete repos group perm users_group
m.connect('delete_repos_group_users_group_perm',
"/delete_repos_group_users_group_perm/{group_name:.*}",
action="delete_repos_group_users_group_perm",
#ADMIN USER REST ROUTES
controller='admin/users') as m:
m.connect("users", "/users",
m.connect("formatted_users", "/users.{format}",
m.connect("new_user", "/users/new",
m.connect("formatted_new_user", "/users/new.{format}",
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",
m.connect("user", "/users/{id}",
action="show", conditions=dict(method=["GET"]))
m.connect("formatted_user", "/users/{id}.{format}",
#EXTRAS USER ROUTES
m.connect("user_perm", "/users_perm/{id}",
action="update_perm", conditions=dict(method=["PUT"]))
m.connect("user_emails", "/users_emails/{id}",
action="add_email", conditions=dict(method=["PUT"]))
m.connect("user_emails_delete", "/users_emails/{id}",
action="delete_email", conditions=dict(method=["DELETE"]))
#ADMIN USERS GROUPS REST ROUTES
controller='admin/users_groups') as m:
m.connect("users_groups", "/users_groups",
m.connect("formatted_users_groups", "/users_groups.{format}",
m.connect("new_users_group", "/users_groups/new",
m.connect("formatted_new_users_group", "/users_groups/new.{format}",
m.connect("update_users_group", "/users_groups/{id}",
m.connect("delete_users_group", "/users_groups/{id}",
m.connect("edit_users_group", "/users_groups/{id}/edit",
m.connect("formatted_edit_users_group",
"/users_groups/{id}.{format}/edit",
m.connect("users_group", "/users_groups/{id}",
m.connect("formatted_users_group", "/users_groups/{id}.{format}",
m.connect("users_group_perm", "/users_groups_perm/{id}",
#ADMIN GROUP REST ROUTES
rmap.resource('group', 'groups',
controller='admin/groups', path_prefix=ADMIN_PREFIX)
#ADMIN PERMISSIONS REST ROUTES
rmap.resource('permission', 'permissions',
controller='admin/permissions', path_prefix=ADMIN_PREFIX)
##ADMIN LDAP SETTINGS
rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX,
controller='admin/ldap_settings', action='ldap_settings',
conditions=dict(method=["POST"]))
rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX,
controller='admin/ldap_settings')
#ADMIN SETTINGS REST ROUTES
controller='admin/settings') as m:
m.connect("admin_settings", "/settings",
m.connect("formatted_admin_settings", "/settings.{format}",
m.connect("admin_new_setting", "/settings/new",
m.connect("formatted_admin_new_setting", "/settings/new.{format}",
m.connect("/settings/{setting_id}",
m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
m.connect("formatted_admin_edit_setting",
"/settings/{setting_id}.{format}/edit",
m.connect("admin_setting", "/settings/{setting_id}",
m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
m.connect("admin_settings_my_account", "/my_account",
action="my_account", conditions=dict(method=["GET"]))
m.connect("admin_settings_my_account_update", "/my_account_update",
action="my_account_update", conditions=dict(method=["PUT"]))
m.connect("admin_settings_create_repository", "/create_repository",
action="create_repository", conditions=dict(method=["GET"]))
m.connect("admin_settings_my_repos", "/my_account/repos",
action="my_account_my_repos", conditions=dict(method=["GET"]))
m.connect("admin_settings_my_pullrequests", "/my_account/pull_requests",
action="my_account_my_pullrequests", conditions=dict(method=["GET"]))
#NOTIFICATION REST ROUTES
controller='admin/notifications') as m:
m.connect("notifications", "/notifications",
m.connect("notifications_mark_all_read", "/notifications/mark_all_read",
action="mark_all_read", conditions=dict(method=["GET"]))
m.connect("formatted_notifications", "/notifications.{format}",
m.connect("new_notification", "/notifications/new",
m.connect("formatted_new_notification", "/notifications/new.{format}",
m.connect("/notification/{notification_id}",
m.connect("edit_notification", "/notification/{notification_id}/edit",
m.connect("formatted_edit_notification",
"/notification/{notification_id}.{format}/edit",
m.connect("notification", "/notification/{notification_id}",
m.connect("formatted_notification", "/notifications/{notification_id}.{format}",
#ADMIN MAIN PAGES
controller='admin/admin') as m:
m.connect('admin_home', '', action='index')
m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
action='add_repo')
# API V2
controller='api/api') as m:
m.connect('api', '/api')
#USER JOURNAL
rmap.connect('journal', '%s/journal' % ADMIN_PREFIX,
controller='journal', action='index')
rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX,
controller='journal', action='journal_rss')
rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX,
controller='journal', action='journal_atom')
rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
controller='journal', action="public_journal")
rmap.connect('public_journal_rss', '%s/public_journal/rss' % ADMIN_PREFIX,
controller='journal', action="public_journal_rss")
rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % ADMIN_PREFIX,
rmap.connect('public_journal_atom',
'%s/public_journal/atom' % ADMIN_PREFIX, controller='journal',
action="public_journal_atom")
rmap.connect('public_journal_atom_old',
'%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
rmap.connect('toggle_following', '%s/toggle_following' % ADMIN_PREFIX,
controller='journal', action='toggle_following',
#SEARCH
rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',)
rmap.connect('search_repo', '%s/search/{search_repo:.*}' % ADMIN_PREFIX,
controller='search')
#LOGIN/LOGOUT/REGISTER/SIGN IN
rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
action='logout')
rmap.connect('register', '%s/register' % ADMIN_PREFIX, controller='login',
action='register')
rmap.connect('reset_password', '%s/password_reset' % ADMIN_PREFIX,
controller='login', action='password_reset')
rmap.connect('reset_password_confirmation',
'%s/password_reset_confirmation' % ADMIN_PREFIX,
controller='login', action='password_reset_confirmation')
#FEEDS
rmap.connect('rss_feed_home', '/{repo_name:.*?}/feed/rss',
controller='feed', action='rss',
conditions=dict(function=check_repo))
rmap.connect('atom_feed_home', '/{repo_name:.*?}/feed/atom',
controller='feed', action='atom',
# REPOSITORY ROUTES
rmap.connect('summary_home', '/{repo_name:.*?}',
controller='summary',
rmap.connect('repos_group_home', '/{group_name:.*}',
controller='admin/repos_groups', action="show_by_name",
conditions=dict(function=check_group))
rmap.connect('changeset_home', '/{repo_name:.*?}/changeset/{revision}',
controller='changeset', revision='tip',
rmap.connect('changeset_comment',
from rhodecode.tests import *
from rhodecode.lib.utils import invalidate_cache
from rhodecode.model.repo import RepoModel
from rhodecode.tests.models.common import _make_repo
from rhodecode.model.meta import Session
class TestSummaryController(TestController):
def test_index(self):
self.log_user()
ID = Repository.get_by_repo_name(HG_REPO).repo_id
response = self.app.get(url(controller='summary',
action='index',
repo_name=HG_REPO))
#repo type
response.mustcontain(
"""<img style="margin-bottom:2px" class="icon" """
"""title="Mercurial repository" alt="Mercurial repository" """
"""src="/images/icons/hgicon.png"/>"""
)
"""title="public repository" alt="public """
"""repository" src="/images/icons/lock_open.png"/>"""
#codes stats
self._enable_stats()
invalidate_cache('get_repo_cached_%s' % HG_REPO)
response = self.app.get(url(controller='summary', action='index',
"""var data = [["py", {"count": 42, "desc": ["Python"]}], """
"""["rst", {"count": 11, "desc": ["Rst"]}], """
"""["sh", {"count": 2, "desc": ["Bash"]}], """
"""["makefile", {"count": 1, "desc": ["Makefile", "Makefile"]}],"""
""" ["cfg", {"count": 1, "desc": ["Ini"]}], """
"""["css", {"count": 1, "desc": ["Css"]}], """
"""["bat", {"count": 1, "desc": ["Batch"]}]];"""
# clone url...
response.mustcontain("""<input style="width:80%%;margin-left:105px" type="text" id="clone_url" readonly="readonly" value="http://test_admin@localhost:80/%s"/>""" % HG_REPO)
response.mustcontain("""<input style="display:none;width:80%%;margin-left:105px" type="text" id="clone_url_id" readonly="readonly" value="http://test_admin@localhost:80/_%s"/>""" % ID)
def test_index_git(self):
ID = Repository.get_by_repo_name(GIT_REPO).repo_id
repo_name=GIT_REPO))
"""title="Git repository" alt="Git repository" """
"""src="/images/icons/giticon.png"/>"""
response.mustcontain("""<input style="width:80%%;margin-left:105px" type="text" id="clone_url" readonly="readonly" value="http://test_admin@localhost:80/%s"/>""" % GIT_REPO)
def test_index_by_id_hg(self):
repo_name='_%s' % ID))
response.mustcontain("""<img style="margin-bottom:2px" class="icon" """
"""title="Mercurial repository" alt="Mercurial """
"""repository" src="/images/icons/hgicon.png"/>""")
"""repository" src="/images/icons/lock_open.png"/>""")
def test_index_by_repo_having_id_path_in_name_hg(self):
_make_repo(name='repo_1')
Session().commit()
repo_name='repo_1'))
response.mustcontain("""repo_1""")
finally:
RepoModel().delete(Repository.get_by_repo_name('repo_1'))
def test_index_by_id_git(self):
"""title="Git repository" alt="Git """
"""repository" src="/images/icons/giticon.png"/>""")
def _enable_stats(self):
r = Repository.get_by_repo_name(HG_REPO)
r.enable_statistics = True
self.Session.add(r)
self.Session.commit()
Status change: