diff --git a/rhodecode/apps/_base/__init__.py b/rhodecode/apps/_base/__init__.py
--- a/rhodecode/apps/_base/__init__.py
+++ b/rhodecode/apps/_base/__init__.py
@@ -362,14 +362,22 @@ class RepoRoutePredicate(object):
repo_model = repo.RepoModel()
by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
+ def redirect_if_creating(db_repo):
+ if db_repo.repo_state in [repo.Repository.STATE_PENDING]:
+ raise HTTPFound(
+ request.route_path('repo_creating',
+ repo_name=db_repo.repo_name))
+
if by_name_match:
# register this as request object we can re-use later
request.db_repo = by_name_match
+ redirect_if_creating(by_name_match)
return True
by_id_match = repo_model.get_repo_by_id(repo_name)
if by_id_match:
request.db_repo = by_id_match
+ redirect_if_creating(by_id_match)
return True
return False
diff --git a/rhodecode/apps/repository/__init__.py b/rhodecode/apps/repository/__init__.py
--- a/rhodecode/apps/repository/__init__.py
+++ b/rhodecode/apps/repository/__init__.py
@@ -22,6 +22,15 @@ from rhodecode.apps._base import add_rou
def includeme(config):
+ # repo creating checks, special cases that aren't repo routes
+ config.add_route(
+ name='repo_creating',
+ pattern='/{repo_name:.*?[^/]}/repo_creating')
+
+ config.add_route(
+ name='repo_creating_check',
+ pattern='/{repo_name:.*?[^/]}/repo_creating_check')
+
# Summary
# NOTE(marcink): one additional route is defined in very bottom, catch
# all pattern
diff --git a/rhodecode/apps/repository/tests/test_repo_summary.py b/rhodecode/apps/repository/tests/test_repo_summary.py
--- a/rhodecode/apps/repository/tests/test_repo_summary.py
+++ b/rhodecode/apps/repository/tests/test_repo_summary.py
@@ -47,8 +47,8 @@ def route_path(name, params=None, **kwar
'repo_summary': '/{repo_name}',
'repo_stats': '/{repo_name}/repo_stats/{commit_id}',
'repo_refs_data': '/{repo_name}/refs-data',
- 'repo_refs_changelog_data': '/{repo_name}/refs-data-changelog'
-
+ 'repo_refs_changelog_data': '/{repo_name}/refs-data-changelog',
+ 'repo_creating_check': '/{repo_name}/repo_creating_check',
}[name].format(**kwargs)
if params:
diff --git a/rhodecode/apps/repository/views/repo_checks.py b/rhodecode/apps/repository/views/repo_checks.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/apps/repository/views/repo_checks.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2011-2017 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/
+
+import logging
+
+from pyramid.view import view_config
+from pyramid.httpexceptions import HTTPFound, HTTPNotFound
+
+from rhodecode.apps._base import BaseAppView
+from rhodecode.lib import helpers as h
+from rhodecode.lib.auth import (NotAnonymous, HasRepoPermissionAny)
+from rhodecode.model.db import Repository
+
+log = logging.getLogger(__name__)
+
+
+class RepoChecksView(BaseAppView):
+ def load_default_context(self):
+ c = self._get_local_tmpl_context()
+ self._register_global_c(c)
+ return c
+
+ @NotAnonymous()
+ @view_config(
+ route_name='repo_creating', request_method='GET',
+ renderer='rhodecode:templates/admin/repos/repo_creating.mako')
+ def repo_creating(self):
+ c = self.load_default_context()
+
+ repo_name = self.request.matchdict['repo_name']
+ db_repo = Repository.get_by_repo_name(repo_name)
+ if not db_repo:
+ raise HTTPNotFound()
+
+ # check if maybe repo is already created
+ if db_repo.repo_state in [Repository.STATE_CREATED]:
+ # re-check permissions before redirecting to prevent resource
+ # discovery by checking the 302 code
+ perm_set = ['repository.read', 'repository.write', 'repository.admin']
+ has_perm = HasRepoPermissionAny(*perm_set)(
+ db_repo.repo_name, 'Repo Creating check')
+ if not has_perm:
+ raise HTTPNotFound()
+
+ raise HTTPFound(h.route_path(
+ 'repo_summary', repo_name=db_repo.repo_name))
+
+ c.task_id = self.request.GET.get('task_id')
+ c.repo_name = repo_name
+
+ return self._get_template_context(c)
+
+ @NotAnonymous()
+ @view_config(
+ route_name='repo_creating_check', request_method='GET',
+ renderer='json_ext')
+ def repo_creating_check(self):
+ _ = self.request.translate
+ task_id = self.request.GET.get('task_id')
+ self.load_default_context()
+
+ repo_name = self.request.matchdict['repo_name']
+
+ if task_id and task_id not in ['None']:
+ import rhodecode
+ from celery.result import AsyncResult
+ if rhodecode.CELERY_ENABLED:
+ task = AsyncResult(task_id)
+ if task.failed():
+ msg = self._log_creation_exception(task.result, repo_name)
+ h.flash(msg, category='error')
+ raise HTTPFound(h.route_path('home'), code=501)
+
+ db_repo = Repository.get_by_repo_name(repo_name)
+ if db_repo and db_repo.repo_state == Repository.STATE_CREATED:
+ if db_repo.clone_uri:
+ clone_uri = db_repo.clone_uri_hidden
+ h.flash(_('Created repository %s from %s')
+ % (db_repo.repo_name, clone_uri), category='success')
+ else:
+ repo_url = h.link_to(
+ db_repo.repo_name,
+ h.route_path('repo_summary', repo_name=db_repo.repo_name))
+ fork = db_repo.fork
+ if fork:
+ fork_name = fork.repo_name
+ h.flash(h.literal(_('Forked repository %s as %s')
+ % (fork_name, repo_url)), category='success')
+ else:
+ h.flash(h.literal(_('Created repository %s') % repo_url),
+ category='success')
+ return {'result': True}
+ return {'result': False}
diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py
--- a/rhodecode/config/routing.py
+++ b/rhodecode/config/routing.py
@@ -416,13 +416,6 @@ def make_map(config):
# REPOSITORY ROUTES
#==========================================================================
- rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
- controller='admin/repos', action='repo_creating',
- requirements=URL_NAME_REQUIREMENTS)
- rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
- controller='admin/repos', action='repo_check',
- requirements=URL_NAME_REQUIREMENTS)
-
# repo edit options
rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
controller='admin/repos', action='edit_fields',
diff --git a/rhodecode/controllers/admin/repos.py b/rhodecode/controllers/admin/repos.py
--- a/rhodecode/controllers/admin/repos.py
+++ b/rhodecode/controllers/admin/repos.py
@@ -31,8 +31,9 @@ from formencode import htmlfill
from pylons import request, tmpl_context as c, url
from pylons.controllers.util import redirect
from pylons.i18n.translation import _
-from webob.exc import HTTPForbidden, HTTPNotFound, HTTPBadRequest
+from webob.exc import HTTPForbidden, HTTPBadRequest
+from pyramid.httpexceptions import HTTPFound
import rhodecode
from rhodecode.lib import auth, helpers as h
from rhodecode.lib.auth import (
@@ -183,9 +184,10 @@ class ReposController(BaseRepoController
h.flash(msg, category='error')
return redirect(h.route_path('home'))
- return redirect(h.url('repo_creating_home',
- repo_name=form_result['repo_name_full'],
- task_id=task_id))
+ raise HTTPFound(
+ h.route_path('repo_creating',
+ repo_name=form_result['repo_name_full'],
+ _query=dict(task_id=task_id)))
# perms check inside
@NotAnonymous()
@@ -239,51 +241,6 @@ class ReposController(BaseRepoController
force_defaults=False
)
- @NotAnonymous()
- def repo_creating(self, repo_name):
- c.repo = repo_name
- c.task_id = request.GET.get('task_id')
- if not c.repo:
- raise HTTPNotFound()
- return render('admin/repos/repo_creating.mako')
-
- @NotAnonymous()
- @jsonify
- def repo_check(self, repo_name):
- c.repo = repo_name
- task_id = request.GET.get('task_id')
-
- if task_id and task_id not in ['None']:
- import rhodecode
- from celery.result import AsyncResult
- if rhodecode.CELERY_ENABLED:
- task = AsyncResult(task_id)
- if task.failed():
- msg = self._log_creation_exception(task.result, c.repo)
- h.flash(msg, category='error')
- return redirect(h.route_path('home'), code=501)
-
- repo = Repository.get_by_repo_name(repo_name)
- if repo and repo.repo_state == Repository.STATE_CREATED:
- if repo.clone_uri:
- clone_uri = repo.clone_uri_hidden
- h.flash(_('Created repository %s from %s')
- % (repo.repo_name, clone_uri), category='success')
- else:
- repo_url = h.link_to(
- repo.repo_name,
- h.route_path('repo_summary',repo_name=repo.repo_name))
- fork = repo.fork
- if fork:
- fork_name = fork.repo_name
- h.flash(h.literal(_('Forked repository %s as %s')
- % (fork_name, repo_url)), category='success')
- else:
- h.flash(h.literal(_('Created repository %s') % repo_url),
- category='success')
- return {'result': True}
- return {'result': False}
-
@HasPermissionAllDecorator('hg.admin')
def show(self, repo_name, format='html'):
"""GET /repos/repo_name: Show a specific item"""
diff --git a/rhodecode/controllers/forks.py b/rhodecode/controllers/forks.py
--- a/rhodecode/controllers/forks.py
+++ b/rhodecode/controllers/forks.py
@@ -30,6 +30,7 @@ from pylons import tmpl_context as c, re
from pylons.controllers.util import redirect
from pylons.i18n.translation import _
+from pyramid.httpexceptions import HTTPFound
import rhodecode.lib.helpers as h
from rhodecode.lib import auth
@@ -191,6 +192,7 @@ class ForksController(BaseRepoController
(repo_name, ))
h.flash(msg, category='error')
- return redirect(h.url('repo_creating_home',
- repo_name=form_result['repo_name_full'],
- task_id=task_id))
+ raise HTTPFound(
+ h.route_path('repo_creating',
+ repo_name=form_result['repo_name_full'],
+ _query=dict(task_id=task_id)))
diff --git a/rhodecode/public/css/main.less b/rhodecode/public/css/main.less
--- a/rhodecode/public/css/main.less
+++ b/rhodecode/public/css/main.less
@@ -1833,6 +1833,11 @@ BIN_FILENODE = 7
}
}
+
+.creation_in_progress {
+ color: @grey4
+}
+
.status_box_menu {
margin: 0;
}
diff --git a/rhodecode/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js
--- a/rhodecode/public/js/rhodecode/routes.js
+++ b/rhodecode/public/js/rhodecode/routes.js
@@ -96,6 +96,8 @@ function registerRCRoutes() {
pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
pyroutes.register('toggle_following', '/_admin/toggle_following', []);
+ pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
+ pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
diff --git a/rhodecode/templates/admin/repos/repo_creating.mako b/rhodecode/templates/admin/repos/repo_creating.mako
--- a/rhodecode/templates/admin/repos/repo_creating.mako
+++ b/rhodecode/templates/admin/repos/repo_creating.mako
@@ -2,14 +2,14 @@
<%inherit file="/base/base.mako"/>
<%def name="title()">
- ${_('%s Creating repository') % c.repo_name}
+ ${_('{} Creating repository').format(c.repo_name)}
%if c.rhodecode_name:
· ${h.branding(c.rhodecode_name)}
%endif
%def>
<%def name="breadcrumbs_links()">
- ${_('Creating repository')} ${c.repo}
+ ${_('Creating repository')} ${c.repo_name}
%def>
<%def name="menu_bar_nav()">
@@ -38,7 +38,7 @@
-%def>
\ No newline at end of file
+%def>
diff --git a/rhodecode/templates/data_table/_dt_elements.mako b/rhodecode/templates/data_table/_dt_elements.mako
--- a/rhodecode/templates/data_table/_dt_elements.mako
+++ b/rhodecode/templates/data_table/_dt_elements.mako
@@ -67,7 +67,9 @@
%endif
%if rstate == 'repo_state_pending':
-
+
+ (${_('creating...')})
+
%endif
%def>
diff --git a/rhodecode/tests/functional/test_admin_repo_groups.py b/rhodecode/tests/functional/test_admin_repo_groups.py
--- a/rhodecode/tests/functional/test_admin_repo_groups.py
+++ b/rhodecode/tests/functional/test_admin_repo_groups.py
@@ -122,8 +122,6 @@ class _BaseTest(TestController):
csrf_token=self.csrf_token))
# run the check page that triggers the flash message
- # response = self.app.get(url('repo_check_home', repo_name=repo_name))
- # assert response.json == {u'result': True}
repo_gr_url = h.route_path(
'repo_group_home', repo_group_name=repo_group_name)
diff --git a/rhodecode/tests/functional/test_admin_repos.py b/rhodecode/tests/functional/test_admin_repos.py
--- a/rhodecode/tests/functional/test_admin_repos.py
+++ b/rhodecode/tests/functional/test_admin_repos.py
@@ -35,14 +35,26 @@ from rhodecode.model.settings import Set
from rhodecode.model.user import UserModel
from rhodecode.tests import (
login_user_session, url, assert_session_flash, TEST_USER_ADMIN_LOGIN,
- TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, HG_REPO, GIT_REPO,
- logout_user_session)
+ TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, logout_user_session)
from rhodecode.tests.fixture import Fixture, error_function
from rhodecode.tests.utils import AssertResponse, repo_on_filesystem
fixture = Fixture()
+def route_path(name, params=None, **kwargs):
+ import urllib
+
+ base_url = {
+ 'repo_summary': '/{repo_name}',
+ 'repo_creating_check': '/{repo_name}/repo_creating_check',
+ }[name].format(**kwargs)
+
+ if params:
+ base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
+ return base_url
+
+
@pytest.mark.usefixtures("app")
class TestAdminRepos(object):
@@ -461,7 +473,8 @@ class TestAdminRepos(object):
repo_name_utf8 = safe_str(repo_name)
# run the check page that triggers the flash message
- response = self.app.get(url('repo_check_home', repo_name=repo_name))
+ response = self.app.get(
+ route_path('repo_creating_check', repo_name=safe_str(repo_name)))
assert response.json == {u'result': True}
flash_msg = u'Created repository {}'.format(
@@ -475,7 +488,8 @@ class TestAdminRepos(object):
assert new_repo.description == description
# test if the repository is visible in the list ?
- response = self.app.get(h.route_path('repo_summary', repo_name=repo_name))
+ response = self.app.get(
+ h.route_path('repo_summary', repo_name=safe_str(repo_name)))
response.mustcontain(repo_name)
response.mustcontain(backend.alias)
diff --git a/rhodecode/tests/functional/test_forks.py b/rhodecode/tests/functional/test_forks.py
--- a/rhodecode/tests/functional/test_forks.py
+++ b/rhodecode/tests/functional/test_forks.py
@@ -32,6 +32,19 @@ from rhodecode.model.meta import Session
fixture = Fixture()
+def route_path(name, params=None, **kwargs):
+ import urllib
+
+ base_url = {
+ 'repo_summary': '/{repo_name}',
+ 'repo_creating_check': '/{repo_name}/repo_creating_check',
+ }[name].format(**kwargs)
+
+ if params:
+ base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
+ return base_url
+
+
class _BaseTest(TestController):
REPO = None
@@ -134,7 +147,8 @@ class _BaseTest(TestController):
assert repo.fork.repo_name == self.REPO
# run the check page that triggers the flash message
- response = self.app.get(url('repo_check_home', repo_name=fork_name_full))
+ response = self.app.get(
+ route_path('repo_creating_check', repo_name=fork_name_full))
# test if we have a message that fork is ok
assert_session_flash(response,
'Forked repository %s as %s'
@@ -180,7 +194,8 @@ class _BaseTest(TestController):
assert repo.fork.repo_name == self.REPO
# run the check page that triggers the flash message
- response = self.app.get(url('repo_check_home', repo_name=fork_name))
+ response = self.app.get(
+ route_path('repo_creating_check', repo_name=fork_name))
# test if we have a message that fork is ok
assert_session_flash(response,
'Forked repository %s as %s'