diff --git a/Gruntfile.js b/Gruntfile.js
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -60,7 +60,7 @@ module.exports = function(grunt) {
'<%= dirs.js.src %>/rhodecode/widgets/multiselect.js',
// Rhodecode components
- '<%= dirs.js.src %>/rhodecode/pyroutes.js',
+ '<%= dirs.js.src %>/rhodecode/init.js',
'<%= dirs.js.src %>/rhodecode/codemirror.js',
'<%= dirs.js.src %>/rhodecode/comments.js',
'<%= dirs.js.src %>/rhodecode/constants.js',
diff --git a/rhodecode/config/environment.py b/rhodecode/config/environment.py
--- a/rhodecode/config/environment.py
+++ b/rhodecode/config/environment.py
@@ -80,6 +80,35 @@ def load_environment(global_conf, app_co
config['app_conf'].get('celery.always.eager'))
config['routes.map'] = make_map(config)
+ jsroutes = config['routes.map'].jsroutes()
+ statements = []
+ for url_name, url, fields in jsroutes:
+ statements.append(
+ "pyroutes.register('%s', '%s', %s);" % (url_name, url, fields))
+ import io
+ import textwrap
+ template = textwrap.dedent(u'''
+/******************************************************************************
+ * *
+ * DO NOT CHANGE THIS FILE MANUALLY *
+ * *
+ * *
+ * This file is automatically generated when the app starts up. *
+ * *
+ * To add a route here pass jsroute=True to the route definition in the app *
+ * *
+ ******************************************************************************/
+function registerRCRoutes() {
+ // routes registration
+ %s
+}
+''').strip()
+ content = template % '\n '.join(statements)
+ js_routes_filepath = os.path.join(
+ paths['static_files'], 'js', 'rhodecode', 'routes.js')
+ with io.open(js_routes_filepath, 'w', encoding='utf-8') as f:
+ f.write(content)
+
config['pylons.app_globals'] = app_globals.Globals(config)
config['pylons.h'] = helpers
rhodecode.CONFIG = config
diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py
--- a/rhodecode/config/routing.py
+++ b/rhodecode/config/routing.py
@@ -29,6 +29,7 @@ IMPORTANT: if you change any routing her
and _route_name variable which uses some of stored naming here to do redirects.
"""
import os
+import re
from routes import Mapper
from rhodecode.config import routing_links
@@ -50,9 +51,61 @@ URL_NAME_REQUIREMENTS = {
}
+class JSRoutesAwareMapper(Mapper):
+ """
+ Wrapper for routes.Mapper to make pyroutes compatible url definitions
+ """
+ _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
+ _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
+ def __init__(self, *args, **kw):
+ super(JSRoutesAwareMapper, self).__init__(*args, **kw)
+ self._jsroutes = []
+
+ def connect(self, *args, **kw):
+ """
+ Wrapper for connect to take an extra argument jsroute=True
+
+ :param jsroute: boolean, if True will add the route to the pyroutes list
+ """
+ if kw.pop('jsroute', False):
+ if not self._named_route_regex.match(args[0]):
+ # import pdb;pdb.set_trace()
+ raise Exception('only named routes can be added to pyroutes')
+ self._jsroutes.append(args[0])
+
+ super(JSRoutesAwareMapper, self).connect(*args, **kw)
+
+ def _extract_route_information(self, route):
+ """
+ Convert a route into tuple(name, path, args), eg:
+ ('user_profile', '/profile/%(username)s', ['username'])
+ """
+ routepath = route.routepath
+ def replace(matchobj):
+ if matchobj.group(1):
+ return "%%(%s)s" % matchobj.group(1).split(':')[0]
+ else:
+ return "%%(%s)s" % matchobj.group(2)
+
+ routepath = self._argument_prog.sub(replace, routepath)
+ return (
+ route.name,
+ routepath,
+ [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
+ for arg in self._argument_prog.findall(route.routepath)]
+ )
+
+ def jsroutes(self):
+ """
+ Return a list of pyroutes.js compatible routes
+ """
+ for route_name in self._jsroutes:
+ yield self._extract_route_information(self._routenames[route_name])
+
+
def make_map(config):
"""Create, configure and return the routes Mapper"""
- rmap = Mapper(directory=config['pylons.paths']['controllers'],
+ rmap = JSRoutesAwareMapper(directory=config['pylons.paths']['controllers'],
always_scan=config['debug'])
rmap.minimization = False
rmap.explicit = False
@@ -124,14 +177,14 @@ def make_map(config):
#==========================================================================
# MAIN PAGE
- rmap.connect('home', '/', controller='home', action='index')
+ rmap.connect('home', '/', controller='home', action='index', jsroute=True)
rmap.connect('goto_switcher_data', '/_goto_data', controller='home',
action='goto_switcher_data')
rmap.connect('repo_list_data', '/_repos', controller='home',
action='repo_list_data')
rmap.connect('user_autocomplete_data', '/_users', controller='home',
- action='user_autocomplete_data')
+ action='user_autocomplete_data', jsroute=True)
rmap.connect('user_group_autocomplete_data', '/_user_groups', controller='home',
action='user_group_autocomplete_data')
@@ -167,7 +220,7 @@ def make_map(config):
action='create', conditions={'method': ['POST']})
m.connect('repos', '/repos',
action='index', conditions={'method': ['GET']})
- m.connect('new_repo', '/create_repository',
+ m.connect('new_repo', '/create_repository', jsroute=True,
action='create_repository', conditions={'method': ['GET']})
m.connect('/repos/{repo_name}',
action='update', conditions={'method': ['PUT'],
@@ -303,22 +356,29 @@ def make_map(config):
function=check_user_group)
# EXTRAS USER GROUP ROUTES
- m.connect('edit_user_group_global_perms', '/user_groups/{user_group_id}/edit/global_permissions',
+ m.connect('edit_user_group_global_perms',
+ '/user_groups/{user_group_id}/edit/global_permissions',
action='edit_global_perms', conditions={'method': ['GET']})
- m.connect('edit_user_group_global_perms', '/user_groups/{user_group_id}/edit/global_permissions',
+ m.connect('edit_user_group_global_perms',
+ '/user_groups/{user_group_id}/edit/global_permissions',
action='update_global_perms', conditions={'method': ['PUT']})
- m.connect('edit_user_group_perms_summary', '/user_groups/{user_group_id}/edit/permissions_summary',
+ m.connect('edit_user_group_perms_summary',
+ '/user_groups/{user_group_id}/edit/permissions_summary',
action='edit_perms_summary', conditions={'method': ['GET']})
- m.connect('edit_user_group_perms', '/user_groups/{user_group_id}/edit/permissions',
+ m.connect('edit_user_group_perms',
+ '/user_groups/{user_group_id}/edit/permissions',
action='edit_perms', conditions={'method': ['GET']})
- m.connect('edit_user_group_perms', '/user_groups/{user_group_id}/edit/permissions',
+ m.connect('edit_user_group_perms',
+ '/user_groups/{user_group_id}/edit/permissions',
action='update_perms', conditions={'method': ['PUT']})
- m.connect('edit_user_group_advanced', '/user_groups/{user_group_id}/edit/advanced',
+ m.connect('edit_user_group_advanced',
+ '/user_groups/{user_group_id}/edit/advanced',
action='edit_advanced', conditions={'method': ['GET']})
- m.connect('edit_user_group_members', '/user_groups/{user_group_id}/edit/members',
+ m.connect('edit_user_group_members',
+ '/user_groups/{user_group_id}/edit/members', jsroute=True,
action='edit_members', conditions={'method': ['GET']})
# ADMIN PERMISSIONS ROUTES
@@ -516,9 +576,9 @@ def make_map(config):
controller='admin/gists') as m:
m.connect('gists', '/gists',
action='create', conditions={'method': ['POST']})
- m.connect('gists', '/gists',
+ m.connect('gists', '/gists', jsroute=True,
action='index', conditions={'method': ['GET']})
- m.connect('new_gist', '/gists/new',
+ m.connect('new_gist', '/gists/new', jsroute=True,
action='new', conditions={'method': ['GET']})
m.connect('/gists/{gist_id}',
@@ -584,7 +644,7 @@ def make_map(config):
action='public_journal_atom')
rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,),
- controller='journal', action='toggle_following',
+ controller='journal', action='toggle_following', jsroute=True,
conditions={'method': ['POST']})
# FULL TEXT SEARCH
@@ -621,17 +681,17 @@ def make_map(config):
rmap.connect('repo_stats', '/{repo_name}/repo_stats/{commit_id}',
controller='summary', action='repo_stats',
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('repo_refs_data', '/{repo_name}/refs-data',
- controller='summary', action='repo_refs_data',
+ controller='summary', action='repo_refs_data', jsroute=True,
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog',
controller='summary', action='repo_refs_changelog_data',
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
- controller='changeset', revision='tip',
+ controller='changeset', revision='tip', jsroute=True,
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
@@ -644,12 +704,13 @@ def make_map(config):
requirements=URL_NAME_REQUIREMENTS)
# repo edit options
- rmap.connect('edit_repo', '/{repo_name}/settings',
+ rmap.connect('edit_repo', '/{repo_name}/settings', jsroute=True,
controller='admin/repos', action='edit',
conditions={'method': ['GET'], 'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('edit_repo_perms', '/{repo_name}/settings/permissions',
+ jsroute=True,
controller='admin/repos', action='edit_permissions',
conditions={'method': ['GET'], 'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
@@ -781,13 +842,13 @@ def make_map(config):
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_comment',
- '/{repo_name}/changeset/{revision}/comment',
+ '/{repo_name}/changeset/{revision}/comment', jsroute=True,
controller='changeset', revision='tip', action='comment',
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
rmap.connect('changeset_comment_preview',
- '/{repo_name}/changeset/comment/preview',
+ '/{repo_name}/changeset/comment/preview', jsroute=True,
controller='changeset', action='preview_comment',
conditions={'function': check_repo, 'method': ['POST']},
requirements=URL_NAME_REQUIREMENTS)
@@ -796,11 +857,11 @@ def make_map(config):
'/{repo_name}/changeset/comment/{comment_id}/delete',
controller='changeset', action='delete_comment',
conditions={'function': check_repo, 'method': ['DELETE']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('changeset_info', '/changeset_info/{repo_name}/{revision}',
controller='changeset', action='changeset_info',
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('compare_home',
'/{repo_name}/compare',
@@ -812,33 +873,33 @@ def make_map(config):
'/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}',
controller='compare', action='compare',
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('pullrequest_home',
'/{repo_name}/pull-request/new', controller='pullrequests',
action='index', conditions={'function': check_repo,
'method': ['GET']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('pullrequest',
'/{repo_name}/pull-request/new', controller='pullrequests',
action='create', conditions={'function': check_repo,
'method': ['POST']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('pullrequest_repo_refs',
'/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
controller='pullrequests',
action='get_repo_refs',
conditions={'function': check_repo, 'method': ['GET']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('pullrequest_repo_destinations',
'/{repo_name}/pull-request/repo-destinations',
controller='pullrequests',
action='get_repo_destinations',
conditions={'function': check_repo, 'method': ['GET']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('pullrequest_show',
'/{repo_name}/pull-request/{pull_request_id}',
@@ -852,7 +913,7 @@ def make_map(config):
controller='pullrequests',
action='update', conditions={'function': check_repo,
'method': ['PUT']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('pullrequest_merge',
'/{repo_name}/pull-request/{pull_request_id}',
@@ -873,20 +934,20 @@ def make_map(config):
controller='pullrequests',
action='show_all', conditions={'function': check_repo,
'method': ['GET']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('pullrequest_comment',
'/{repo_name}/pull-request-comment/{pull_request_id}',
controller='pullrequests',
action='comment', conditions={'function': check_repo,
'method': ['POST']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('pullrequest_comment_delete',
'/{repo_name}/pull-request-comment/{comment_id}/delete',
controller='pullrequests', action='delete_comment',
conditions={'function': check_repo, 'method': ['DELETE']},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('summary_home_explicit', '/{repo_name}/summary',
controller='summary', conditions={'function': check_repo},
@@ -904,7 +965,7 @@ def make_map(config):
controller='bookmarks', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
- rmap.connect('changelog_home', '/{repo_name}/changelog',
+ rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
controller='changelog', conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
@@ -913,21 +974,21 @@ def make_map(config):
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
- rmap.connect('changelog_file_home', '/{repo_name}/changelog/{revision}/{f_path}',
+ rmap.connect('changelog_file_home',
+ '/{repo_name}/changelog/{revision}/{f_path}',
controller='changelog', f_path=None,
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('changelog_details', '/{repo_name}/changelog_details/{cs}',
controller='changelog', action='changelog_details',
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
- rmap.connect('files_home',
- '/{repo_name}/files/{revision}/{f_path}',
+ rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}',
controller='files', revision='tip', f_path='',
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('files_home_simple_catchrev',
'/{repo_name}/files/{revision}',
@@ -945,13 +1006,13 @@ def make_map(config):
'/{repo_name}/history/{revision}/{f_path}',
controller='files', action='history', revision='tip', f_path='',
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('files_authors_home',
'/{repo_name}/authors/{revision}/{f_path}',
controller='files', action='authors', revision='tip', f_path='',
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}',
controller='files', action='diff', f_path='',
@@ -1030,19 +1091,19 @@ def make_map(config):
rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}',
controller='files', action='archivefile',
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('files_nodelist_home',
'/{repo_name}/nodelist/{revision}/{f_path}',
controller='files', action='nodelist',
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('files_metadata_list_home',
'/{repo_name}/metadata_list/{revision}/{f_path}',
controller='files', action='metadata_list',
conditions={'function': check_repo},
- requirements=URL_NAME_REQUIREMENTS)
+ requirements=URL_NAME_REQUIREMENTS, jsroute=True)
rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
controller='forks', action='fork_create',
@@ -1073,11 +1134,12 @@ def make_map(config):
# catch all, at the end
_connect_with_slash(
- rmap, 'summary_home', '/{repo_name}',
+ rmap, 'summary_home', '/{repo_name}', jsroute=True,
controller='summary', action='index',
conditions={'function': check_repo},
requirements=URL_NAME_REQUIREMENTS)
+ rmap.jsroutes()
return rmap
diff --git a/rhodecode/public/js/src/rhodecode/pyroutes.js b/rhodecode/public/js/rhodecode/routes.js
rename from rhodecode/public/js/src/rhodecode/pyroutes.js
rename to rhodecode/public/js/rhodecode/routes.js
--- a/rhodecode/public/js/src/rhodecode/pyroutes.js
+++ b/rhodecode/public/js/rhodecode/routes.js
@@ -1,46 +1,49 @@
-/* This file is automatically generated. DO NOT change it manually.
- * If this file needs to be modified, edit
- * rhodecode/utils/file_generation/js_routes_data.py
- * and run the script invoke -r scripts/ generate.js-routes .
- */
+/******************************************************************************
+ * *
+ * DO NOT CHANGE THIS FILE MANUALLY *
+ * *
+ * *
+ * This file is automatically generated when the app starts up. *
+ * *
+ * To add a route here pass jsroute=True to the route definition in the app *
+ * *
+ ******************************************************************************/
function registerRCRoutes() {
// routes registration
pyroutes.register('home', '/', []);
- pyroutes.register('new_gist', '/_admin/gists/new', []);
- pyroutes.register('gists', '/_admin/gists', []);
+ pyroutes.register('user_autocomplete_data', '/_users', []);
pyroutes.register('new_repo', '/_admin/create_repository', []);
- pyroutes.register('summary_home', '/%(repo_name)s', ['repo_name']);
- pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']);
- pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
+ pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
+ pyroutes.register('gists', '/_admin/gists', []);
+ pyroutes.register('new_gist', '/_admin/gists/new', []);
+ pyroutes.register('toggle_following', '/_admin/toggle_following', []);
+ pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
+ pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
+ pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
+ pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
- pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
- pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
- pyroutes.register('user_autocomplete_data', '/_users', []);
- pyroutes.register('toggle_following', '/_admin/toggle_following', []);
- pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
- pyroutes.register('changeset_info', '/changeset_info/%(repo_name)s/%(revision)s', ['repo_name', 'revision']);
- pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
- pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
- pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
+ pyroutes.register('changeset_info', '/changeset_info/%(repo_name)s/%(revision)s', ['repo_name', 'revision']);
+ pyroutes.register('compare_url', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
+ pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
+ pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
+ pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
+ pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']);
+ pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
+ pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
+ pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
+ pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
+ pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']);
+ pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
+ pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
+ pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
+ pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
pyroutes.register('files_archive_home', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
pyroutes.register('files_nodelist_home', '/%(repo_name)s/nodelist/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
pyroutes.register('files_metadata_list_home', '/%(repo_name)s/metadata_list/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
- pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
- pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
- pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
- pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
- pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
- pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
- pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
- pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
- pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
- pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
- pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']);
- pyroutes.register('compare_url', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
-}
-
-registerRCRoutes();
\ No newline at end of file
+ pyroutes.register('summary_home_slash', '/%(repo_name)s/', ['repo_name']);
+ pyroutes.register('summary_home', '/%(repo_name)s', ['repo_name']);
+}
\ No newline at end of file
diff --git a/rhodecode/public/js/src/rhodecode/init.js b/rhodecode/public/js/src/rhodecode/init.js
new file mode 100644
--- /dev/null
+++ b/rhodecode/public/js/src/rhodecode/init.js
@@ -0,0 +1,26 @@
+// # Copyright (C) 2010-2016 RhodeCode GmbH
+// #
+// # This program is free software: you can redistribute it and/or modify
+// # it under the terms of the GNU Affero General Public License, version 3
+// # (only), as published by the Free Software Foundation.
+// #
+// # 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 Affero General Public License
+// # along with this program. If not, see .
+// #
+// # This program is dual-licensed. If you wish to learn more about the
+// # RhodeCode Enterprise Edition, including its added features, Support services,
+// # and proprietary license terms, please see https://rhodecode.com/licenses/
+
+
+/*
+ * Deferred functions that must run before any rhodecode javascript go here
+ */
+
+registerRCRoutes();
+
+// TODO: move i18n here
diff --git a/rhodecode/templates/base/root.html b/rhodecode/templates/base/root.html
--- a/rhodecode/templates/base/root.html
+++ b/rhodecode/templates/base/root.html
@@ -115,6 +115,7 @@
+