##// END OF EJS Templates
repositories: ported repo_creating checks to pyramid....
marcink -
r1985:f5a73a5e default
parent child Browse files
Show More
@@ -0,0 +1,110 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2011-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import logging
22
23 from pyramid.view import view_config
24 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
25
26 from rhodecode.apps._base import BaseAppView
27 from rhodecode.lib import helpers as h
28 from rhodecode.lib.auth import (NotAnonymous, HasRepoPermissionAny)
29 from rhodecode.model.db import Repository
30
31 log = logging.getLogger(__name__)
32
33
34 class RepoChecksView(BaseAppView):
35 def load_default_context(self):
36 c = self._get_local_tmpl_context()
37 self._register_global_c(c)
38 return c
39
40 @NotAnonymous()
41 @view_config(
42 route_name='repo_creating', request_method='GET',
43 renderer='rhodecode:templates/admin/repos/repo_creating.mako')
44 def repo_creating(self):
45 c = self.load_default_context()
46
47 repo_name = self.request.matchdict['repo_name']
48 db_repo = Repository.get_by_repo_name(repo_name)
49 if not db_repo:
50 raise HTTPNotFound()
51
52 # check if maybe repo is already created
53 if db_repo.repo_state in [Repository.STATE_CREATED]:
54 # re-check permissions before redirecting to prevent resource
55 # discovery by checking the 302 code
56 perm_set = ['repository.read', 'repository.write', 'repository.admin']
57 has_perm = HasRepoPermissionAny(*perm_set)(
58 db_repo.repo_name, 'Repo Creating check')
59 if not has_perm:
60 raise HTTPNotFound()
61
62 raise HTTPFound(h.route_path(
63 'repo_summary', repo_name=db_repo.repo_name))
64
65 c.task_id = self.request.GET.get('task_id')
66 c.repo_name = repo_name
67
68 return self._get_template_context(c)
69
70 @NotAnonymous()
71 @view_config(
72 route_name='repo_creating_check', request_method='GET',
73 renderer='json_ext')
74 def repo_creating_check(self):
75 _ = self.request.translate
76 task_id = self.request.GET.get('task_id')
77 self.load_default_context()
78
79 repo_name = self.request.matchdict['repo_name']
80
81 if task_id and task_id not in ['None']:
82 import rhodecode
83 from celery.result import AsyncResult
84 if rhodecode.CELERY_ENABLED:
85 task = AsyncResult(task_id)
86 if task.failed():
87 msg = self._log_creation_exception(task.result, repo_name)
88 h.flash(msg, category='error')
89 raise HTTPFound(h.route_path('home'), code=501)
90
91 db_repo = Repository.get_by_repo_name(repo_name)
92 if db_repo and db_repo.repo_state == Repository.STATE_CREATED:
93 if db_repo.clone_uri:
94 clone_uri = db_repo.clone_uri_hidden
95 h.flash(_('Created repository %s from %s')
96 % (db_repo.repo_name, clone_uri), category='success')
97 else:
98 repo_url = h.link_to(
99 db_repo.repo_name,
100 h.route_path('repo_summary', repo_name=db_repo.repo_name))
101 fork = db_repo.fork
102 if fork:
103 fork_name = fork.repo_name
104 h.flash(h.literal(_('Forked repository %s as %s')
105 % (fork_name, repo_url)), category='success')
106 else:
107 h.flash(h.literal(_('Created repository %s') % repo_url),
108 category='success')
109 return {'result': True}
110 return {'result': False}
@@ -362,14 +362,22 b' class RepoRoutePredicate(object):'
362 362 repo_model = repo.RepoModel()
363 363 by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
364 364
365 def redirect_if_creating(db_repo):
366 if db_repo.repo_state in [repo.Repository.STATE_PENDING]:
367 raise HTTPFound(
368 request.route_path('repo_creating',
369 repo_name=db_repo.repo_name))
370
365 371 if by_name_match:
366 372 # register this as request object we can re-use later
367 373 request.db_repo = by_name_match
374 redirect_if_creating(by_name_match)
368 375 return True
369 376
370 377 by_id_match = repo_model.get_repo_by_id(repo_name)
371 378 if by_id_match:
372 379 request.db_repo = by_id_match
380 redirect_if_creating(by_id_match)
373 381 return True
374 382
375 383 return False
@@ -22,6 +22,15 b' from rhodecode.apps._base import add_rou'
22 22
23 23 def includeme(config):
24 24
25 # repo creating checks, special cases that aren't repo routes
26 config.add_route(
27 name='repo_creating',
28 pattern='/{repo_name:.*?[^/]}/repo_creating')
29
30 config.add_route(
31 name='repo_creating_check',
32 pattern='/{repo_name:.*?[^/]}/repo_creating_check')
33
25 34 # Summary
26 35 # NOTE(marcink): one additional route is defined in very bottom, catch
27 36 # all pattern
@@ -47,8 +47,8 b' def route_path(name, params=None, **kwar'
47 47 'repo_summary': '/{repo_name}',
48 48 'repo_stats': '/{repo_name}/repo_stats/{commit_id}',
49 49 'repo_refs_data': '/{repo_name}/refs-data',
50 'repo_refs_changelog_data': '/{repo_name}/refs-data-changelog'
51
50 'repo_refs_changelog_data': '/{repo_name}/refs-data-changelog',
51 'repo_creating_check': '/{repo_name}/repo_creating_check',
52 52 }[name].format(**kwargs)
53 53
54 54 if params:
@@ -416,13 +416,6 b' def make_map(config):'
416 416 # REPOSITORY ROUTES
417 417 #==========================================================================
418 418
419 rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
420 controller='admin/repos', action='repo_creating',
421 requirements=URL_NAME_REQUIREMENTS)
422 rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
423 controller='admin/repos', action='repo_check',
424 requirements=URL_NAME_REQUIREMENTS)
425
426 419 # repo edit options
427 420 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
428 421 controller='admin/repos', action='edit_fields',
@@ -31,8 +31,9 b' from formencode import htmlfill'
31 31 from pylons import request, tmpl_context as c, url
32 32 from pylons.controllers.util import redirect
33 33 from pylons.i18n.translation import _
34 from webob.exc import HTTPForbidden, HTTPNotFound, HTTPBadRequest
34 from webob.exc import HTTPForbidden, HTTPBadRequest
35 35
36 from pyramid.httpexceptions import HTTPFound
36 37 import rhodecode
37 38 from rhodecode.lib import auth, helpers as h
38 39 from rhodecode.lib.auth import (
@@ -183,9 +184,10 b' class ReposController(BaseRepoController'
183 184 h.flash(msg, category='error')
184 185 return redirect(h.route_path('home'))
185 186
186 return redirect(h.url('repo_creating_home',
187 repo_name=form_result['repo_name_full'],
188 task_id=task_id))
187 raise HTTPFound(
188 h.route_path('repo_creating',
189 repo_name=form_result['repo_name_full'],
190 _query=dict(task_id=task_id)))
189 191
190 192 # perms check inside
191 193 @NotAnonymous()
@@ -239,51 +241,6 b' class ReposController(BaseRepoController'
239 241 force_defaults=False
240 242 )
241 243
242 @NotAnonymous()
243 def repo_creating(self, repo_name):
244 c.repo = repo_name
245 c.task_id = request.GET.get('task_id')
246 if not c.repo:
247 raise HTTPNotFound()
248 return render('admin/repos/repo_creating.mako')
249
250 @NotAnonymous()
251 @jsonify
252 def repo_check(self, repo_name):
253 c.repo = repo_name
254 task_id = request.GET.get('task_id')
255
256 if task_id and task_id not in ['None']:
257 import rhodecode
258 from celery.result import AsyncResult
259 if rhodecode.CELERY_ENABLED:
260 task = AsyncResult(task_id)
261 if task.failed():
262 msg = self._log_creation_exception(task.result, c.repo)
263 h.flash(msg, category='error')
264 return redirect(h.route_path('home'), code=501)
265
266 repo = Repository.get_by_repo_name(repo_name)
267 if repo and repo.repo_state == Repository.STATE_CREATED:
268 if repo.clone_uri:
269 clone_uri = repo.clone_uri_hidden
270 h.flash(_('Created repository %s from %s')
271 % (repo.repo_name, clone_uri), category='success')
272 else:
273 repo_url = h.link_to(
274 repo.repo_name,
275 h.route_path('repo_summary',repo_name=repo.repo_name))
276 fork = repo.fork
277 if fork:
278 fork_name = fork.repo_name
279 h.flash(h.literal(_('Forked repository %s as %s')
280 % (fork_name, repo_url)), category='success')
281 else:
282 h.flash(h.literal(_('Created repository %s') % repo_url),
283 category='success')
284 return {'result': True}
285 return {'result': False}
286
287 244 @HasPermissionAllDecorator('hg.admin')
288 245 def show(self, repo_name, format='html'):
289 246 """GET /repos/repo_name: Show a specific item"""
@@ -30,6 +30,7 b' from pylons import tmpl_context as c, re'
30 30 from pylons.controllers.util import redirect
31 31 from pylons.i18n.translation import _
32 32
33 from pyramid.httpexceptions import HTTPFound
33 34 import rhodecode.lib.helpers as h
34 35
35 36 from rhodecode.lib import auth
@@ -191,6 +192,7 b' class ForksController(BaseRepoController'
191 192 (repo_name, ))
192 193 h.flash(msg, category='error')
193 194
194 return redirect(h.url('repo_creating_home',
195 repo_name=form_result['repo_name_full'],
196 task_id=task_id))
195 raise HTTPFound(
196 h.route_path('repo_creating',
197 repo_name=form_result['repo_name_full'],
198 _query=dict(task_id=task_id)))
@@ -1833,6 +1833,11 b' BIN_FILENODE = 7'
1833 1833 }
1834 1834 }
1835 1835
1836
1837 .creation_in_progress {
1838 color: @grey4
1839 }
1840
1836 1841 .status_box_menu {
1837 1842 margin: 0;
1838 1843 }
@@ -96,6 +96,8 b' function registerRCRoutes() {'
96 96 pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
97 97 pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
98 98 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
99 pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
100 pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
99 101 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
100 102 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
101 103 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
@@ -2,14 +2,14 b''
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 ${_('%s Creating repository') % c.repo_name}
5 ${_('{} Creating repository').format(c.repo_name)}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10
11 11 <%def name="breadcrumbs_links()">
12 ${_('Creating repository')} ${c.repo}
12 ${_('Creating repository')} ${c.repo_name}
13 13 </%def>
14 14
15 15 <%def name="menu_bar_nav()">
@@ -38,7 +38,7 b''
38 38 <script>
39 39 (function worker() {
40 40 var skipCheck = false;
41 var url = "${h.url('repo_check_home', repo_name=c.repo_name, repo=c.repo, task_id=c.task_id)}";
41 var url = "${h.route_path('repo_creating_check', repo_name=c.repo_name, _query=dict(task_id=c.task_id))}";
42 42 $.ajax({
43 43 url: url,
44 44 complete: function(resp) {
@@ -48,12 +48,12 b''
48 48 if (jsonResponse === undefined) {
49 49 setTimeout(function () {
50 50 // we might have a backend problem, try dashboard again
51 window.location = "${h.route_path('repo_summary', repo_name = c.repo)}";
51 window.location = "${h.route_path('repo_summary', repo_name = c.repo_name)}";
52 52 }, 3000);
53 53 } else {
54 54 if (skipCheck || jsonResponse.result === true) {
55 55 // success, means go to dashboard
56 window.location = "${h.route_path('repo_summary', repo_name = c.repo)}";
56 window.location = "${h.route_path('repo_summary', repo_name = c.repo_name)}";
57 57 } else {
58 58 // Schedule the next request when the current one's complete
59 59 setTimeout(worker, 1000);
@@ -61,10 +61,17 b''
61 61 }
62 62 }
63 63 else {
64 window.location = "${h.route_path('home')}";
64 var payload = {
65 message: {
66 message: _gettext('Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.').format(resp.status, resp.statusText),
67 level: 'error',
68 force: true
69 }
70 };
71 $.Topic('/notifications').publish(payload);
65 72 }
66 73 }
67 74 });
68 75 })();
69 76 </script>
70 </%def> No newline at end of file
77 </%def>
@@ -67,7 +67,9 b''
67 67 <a href="${h.route_path('repo_summary',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a>
68 68 %endif
69 69 %if rstate == 'repo_state_pending':
70 <i class="icon-cogs" title="${_('Repository creating in progress...')}"></i>
70 <span class="creation_in_progress tooltip" title="${_('This repository is being created in a background task')}">
71 (${_('creating...')})
72 </span>
71 73 %endif
72 74 </div>
73 75 </%def>
@@ -122,8 +122,6 b' class _BaseTest(TestController):'
122 122 csrf_token=self.csrf_token))
123 123
124 124 # run the check page that triggers the flash message
125 # response = self.app.get(url('repo_check_home', repo_name=repo_name))
126 # assert response.json == {u'result': True}
127 125 repo_gr_url = h.route_path(
128 126 'repo_group_home', repo_group_name=repo_group_name)
129 127
@@ -35,14 +35,26 b' from rhodecode.model.settings import Set'
35 35 from rhodecode.model.user import UserModel
36 36 from rhodecode.tests import (
37 37 login_user_session, url, assert_session_flash, TEST_USER_ADMIN_LOGIN,
38 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, HG_REPO, GIT_REPO,
39 logout_user_session)
38 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, logout_user_session)
40 39 from rhodecode.tests.fixture import Fixture, error_function
41 40 from rhodecode.tests.utils import AssertResponse, repo_on_filesystem
42 41
43 42 fixture = Fixture()
44 43
45 44
45 def route_path(name, params=None, **kwargs):
46 import urllib
47
48 base_url = {
49 'repo_summary': '/{repo_name}',
50 'repo_creating_check': '/{repo_name}/repo_creating_check',
51 }[name].format(**kwargs)
52
53 if params:
54 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
55 return base_url
56
57
46 58 @pytest.mark.usefixtures("app")
47 59 class TestAdminRepos(object):
48 60
@@ -461,7 +473,8 b' class TestAdminRepos(object):'
461 473 repo_name_utf8 = safe_str(repo_name)
462 474
463 475 # run the check page that triggers the flash message
464 response = self.app.get(url('repo_check_home', repo_name=repo_name))
476 response = self.app.get(
477 route_path('repo_creating_check', repo_name=safe_str(repo_name)))
465 478 assert response.json == {u'result': True}
466 479
467 480 flash_msg = u'Created repository <a href="/{}">{}</a>'.format(
@@ -475,7 +488,8 b' class TestAdminRepos(object):'
475 488 assert new_repo.description == description
476 489
477 490 # test if the repository is visible in the list ?
478 response = self.app.get(h.route_path('repo_summary', repo_name=repo_name))
491 response = self.app.get(
492 h.route_path('repo_summary', repo_name=safe_str(repo_name)))
479 493 response.mustcontain(repo_name)
480 494 response.mustcontain(backend.alias)
481 495
@@ -32,6 +32,19 b' from rhodecode.model.meta import Session'
32 32 fixture = Fixture()
33 33
34 34
35 def route_path(name, params=None, **kwargs):
36 import urllib
37
38 base_url = {
39 'repo_summary': '/{repo_name}',
40 'repo_creating_check': '/{repo_name}/repo_creating_check',
41 }[name].format(**kwargs)
42
43 if params:
44 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
45 return base_url
46
47
35 48 class _BaseTest(TestController):
36 49
37 50 REPO = None
@@ -134,7 +147,8 b' class _BaseTest(TestController):'
134 147 assert repo.fork.repo_name == self.REPO
135 148
136 149 # run the check page that triggers the flash message
137 response = self.app.get(url('repo_check_home', repo_name=fork_name_full))
150 response = self.app.get(
151 route_path('repo_creating_check', repo_name=fork_name_full))
138 152 # test if we have a message that fork is ok
139 153 assert_session_flash(response,
140 154 'Forked repository %s as <a href="/%s">%s</a>'
@@ -180,7 +194,8 b' class _BaseTest(TestController):'
180 194 assert repo.fork.repo_name == self.REPO
181 195
182 196 # run the check page that triggers the flash message
183 response = self.app.get(url('repo_check_home', repo_name=fork_name))
197 response = self.app.get(
198 route_path('repo_creating_check', repo_name=fork_name))
184 199 # test if we have a message that fork is ok
185 200 assert_session_flash(response,
186 201 'Forked repository %s as <a href="/%s">%s</a>'
General Comments 0
You need to be logged in to leave comments. Login now