##// END OF EJS Templates
data-grid-app: added universal function for extracting ordering....
marcink -
r2040:a04ecb8d default
parent child Browse files
Show More
@@ -1,461 +1,471 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import time
21 import time
22 import logging
22 import logging
23 import operator
23
24
24 from pyramid.httpexceptions import HTTPFound
25 from pyramid.httpexceptions import HTTPFound
25
26
26 from rhodecode.lib import helpers as h
27 from rhodecode.lib import helpers as h
27 from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time
28 from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time
28 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
29 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
29 from rhodecode.model import repo
30 from rhodecode.model import repo
30 from rhodecode.model import repo_group
31 from rhodecode.model import repo_group
31 from rhodecode.model.db import User
32 from rhodecode.model.db import User
32 from rhodecode.model.scm import ScmModel
33 from rhodecode.model.scm import ScmModel
33
34
34 log = logging.getLogger(__name__)
35 log = logging.getLogger(__name__)
35
36
36
37
37 ADMIN_PREFIX = '/_admin'
38 ADMIN_PREFIX = '/_admin'
38 STATIC_FILE_PREFIX = '/_static'
39 STATIC_FILE_PREFIX = '/_static'
39
40
40 URL_NAME_REQUIREMENTS = {
41 URL_NAME_REQUIREMENTS = {
41 # group name can have a slash in them, but they must not end with a slash
42 # group name can have a slash in them, but they must not end with a slash
42 'group_name': r'.*?[^/]',
43 'group_name': r'.*?[^/]',
43 'repo_group_name': r'.*?[^/]',
44 'repo_group_name': r'.*?[^/]',
44 # repo names can have a slash in them, but they must not end with a slash
45 # repo names can have a slash in them, but they must not end with a slash
45 'repo_name': r'.*?[^/]',
46 'repo_name': r'.*?[^/]',
46 # file path eats up everything at the end
47 # file path eats up everything at the end
47 'f_path': r'.*',
48 'f_path': r'.*',
48 # reference types
49 # reference types
49 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
50 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
50 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
51 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
51 }
52 }
52
53
53
54
54 def add_route_with_slash(config,name, pattern, **kw):
55 def add_route_with_slash(config,name, pattern, **kw):
55 config.add_route(name, pattern, **kw)
56 config.add_route(name, pattern, **kw)
56 if not pattern.endswith('/'):
57 if not pattern.endswith('/'):
57 config.add_route(name + '_slash', pattern + '/', **kw)
58 config.add_route(name + '_slash', pattern + '/', **kw)
58
59
59
60
60 def add_route_requirements(route_path, requirements=URL_NAME_REQUIREMENTS):
61 def add_route_requirements(route_path, requirements=URL_NAME_REQUIREMENTS):
61 """
62 """
62 Adds regex requirements to pyramid routes using a mapping dict
63 Adds regex requirements to pyramid routes using a mapping dict
63 e.g::
64 e.g::
64 add_route_requirements('{repo_name}/settings')
65 add_route_requirements('{repo_name}/settings')
65 """
66 """
66 for key, regex in requirements.items():
67 for key, regex in requirements.items():
67 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
68 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
68 return route_path
69 return route_path
69
70
70
71
71 def get_format_ref_id(repo):
72 def get_format_ref_id(repo):
72 """Returns a `repo` specific reference formatter function"""
73 """Returns a `repo` specific reference formatter function"""
73 if h.is_svn(repo):
74 if h.is_svn(repo):
74 return _format_ref_id_svn
75 return _format_ref_id_svn
75 else:
76 else:
76 return _format_ref_id
77 return _format_ref_id
77
78
78
79
79 def _format_ref_id(name, raw_id):
80 def _format_ref_id(name, raw_id):
80 """Default formatting of a given reference `name`"""
81 """Default formatting of a given reference `name`"""
81 return name
82 return name
82
83
83
84
84 def _format_ref_id_svn(name, raw_id):
85 def _format_ref_id_svn(name, raw_id):
85 """Special way of formatting a reference for Subversion including path"""
86 """Special way of formatting a reference for Subversion including path"""
86 return '%s@%s' % (name, raw_id)
87 return '%s@%s' % (name, raw_id)
87
88
88
89
89 class TemplateArgs(StrictAttributeDict):
90 class TemplateArgs(StrictAttributeDict):
90 pass
91 pass
91
92
92
93
93 class BaseAppView(object):
94 class BaseAppView(object):
94
95
95 def __init__(self, context, request):
96 def __init__(self, context, request):
96 self.request = request
97 self.request = request
97 self.context = context
98 self.context = context
98 self.session = request.session
99 self.session = request.session
99 self._rhodecode_user = request.user # auth user
100 self._rhodecode_user = request.user # auth user
100 self._rhodecode_db_user = self._rhodecode_user.get_instance()
101 self._rhodecode_db_user = self._rhodecode_user.get_instance()
101 self._maybe_needs_password_change(
102 self._maybe_needs_password_change(
102 request.matched_route.name, self._rhodecode_db_user)
103 request.matched_route.name, self._rhodecode_db_user)
103
104
104 def _maybe_needs_password_change(self, view_name, user_obj):
105 def _maybe_needs_password_change(self, view_name, user_obj):
105 log.debug('Checking if user %s needs password change on view %s',
106 log.debug('Checking if user %s needs password change on view %s',
106 user_obj, view_name)
107 user_obj, view_name)
107 skip_user_views = [
108 skip_user_views = [
108 'logout', 'login',
109 'logout', 'login',
109 'my_account_password', 'my_account_password_update'
110 'my_account_password', 'my_account_password_update'
110 ]
111 ]
111
112
112 if not user_obj:
113 if not user_obj:
113 return
114 return
114
115
115 if user_obj.username == User.DEFAULT_USER:
116 if user_obj.username == User.DEFAULT_USER:
116 return
117 return
117
118
118 now = time.time()
119 now = time.time()
119 should_change = user_obj.user_data.get('force_password_change')
120 should_change = user_obj.user_data.get('force_password_change')
120 change_after = safe_int(should_change) or 0
121 change_after = safe_int(should_change) or 0
121 if should_change and now > change_after:
122 if should_change and now > change_after:
122 log.debug('User %s requires password change', user_obj)
123 log.debug('User %s requires password change', user_obj)
123 h.flash('You are required to change your password', 'warning',
124 h.flash('You are required to change your password', 'warning',
124 ignore_duplicate=True)
125 ignore_duplicate=True)
125
126
126 if view_name not in skip_user_views:
127 if view_name not in skip_user_views:
127 raise HTTPFound(
128 raise HTTPFound(
128 self.request.route_path('my_account_password'))
129 self.request.route_path('my_account_password'))
129
130
130 def _log_creation_exception(self, e, repo_name):
131 def _log_creation_exception(self, e, repo_name):
131 _ = self.request.translate
132 _ = self.request.translate
132 reason = None
133 reason = None
133 if len(e.args) == 2:
134 if len(e.args) == 2:
134 reason = e.args[1]
135 reason = e.args[1]
135
136
136 if reason == 'INVALID_CERTIFICATE':
137 if reason == 'INVALID_CERTIFICATE':
137 log.exception(
138 log.exception(
138 'Exception creating a repository: invalid certificate')
139 'Exception creating a repository: invalid certificate')
139 msg = (_('Error creating repository %s: invalid certificate')
140 msg = (_('Error creating repository %s: invalid certificate')
140 % repo_name)
141 % repo_name)
141 else:
142 else:
142 log.exception("Exception creating a repository")
143 log.exception("Exception creating a repository")
143 msg = (_('Error creating repository %s')
144 msg = (_('Error creating repository %s')
144 % repo_name)
145 % repo_name)
145 return msg
146 return msg
146
147
147 def _get_local_tmpl_context(self, include_app_defaults=False):
148 def _get_local_tmpl_context(self, include_app_defaults=False):
148 c = TemplateArgs()
149 c = TemplateArgs()
149 c.auth_user = self.request.user
150 c.auth_user = self.request.user
150 # TODO(marcink): migrate the usage of c.rhodecode_user to c.auth_user
151 # TODO(marcink): migrate the usage of c.rhodecode_user to c.auth_user
151 c.rhodecode_user = self.request.user
152 c.rhodecode_user = self.request.user
152
153
153 if include_app_defaults:
154 if include_app_defaults:
154 # NOTE(marcink): after full pyramid migration include_app_defaults
155 # NOTE(marcink): after full pyramid migration include_app_defaults
155 # should be turned on by default
156 # should be turned on by default
156 from rhodecode.lib.base import attach_context_attributes
157 from rhodecode.lib.base import attach_context_attributes
157 attach_context_attributes(c, self.request, self.request.user.user_id)
158 attach_context_attributes(c, self.request, self.request.user.user_id)
158
159
159 return c
160 return c
160
161
161 def _register_global_c(self, tmpl_args):
162 def _register_global_c(self, tmpl_args):
162 """
163 """
163 Registers attributes to pylons global `c`
164 Registers attributes to pylons global `c`
164 """
165 """
165
166
166 # TODO(marcink): remove once pyramid migration is finished
167 # TODO(marcink): remove once pyramid migration is finished
167 from pylons import tmpl_context as c
168 from pylons import tmpl_context as c
168 try:
169 try:
169 for k, v in tmpl_args.items():
170 for k, v in tmpl_args.items():
170 setattr(c, k, v)
171 setattr(c, k, v)
171 except TypeError:
172 except TypeError:
172 log.exception('Failed to register pylons C')
173 log.exception('Failed to register pylons C')
173 pass
174 pass
174
175
175 def _get_template_context(self, tmpl_args):
176 def _get_template_context(self, tmpl_args):
176 self._register_global_c(tmpl_args)
177 self._register_global_c(tmpl_args)
177
178
178 local_tmpl_args = {
179 local_tmpl_args = {
179 'defaults': {},
180 'defaults': {},
180 'errors': {},
181 'errors': {},
181 # register a fake 'c' to be used in templates instead of global
182 # register a fake 'c' to be used in templates instead of global
182 # pylons c, after migration to pyramid we should rename it to 'c'
183 # pylons c, after migration to pyramid we should rename it to 'c'
183 # make sure we replace usage of _c in templates too
184 # make sure we replace usage of _c in templates too
184 '_c': tmpl_args
185 '_c': tmpl_args
185 }
186 }
186 local_tmpl_args.update(tmpl_args)
187 local_tmpl_args.update(tmpl_args)
187 return local_tmpl_args
188 return local_tmpl_args
188
189
189 def load_default_context(self):
190 def load_default_context(self):
190 """
191 """
191 example:
192 example:
192
193
193 def load_default_context(self):
194 def load_default_context(self):
194 c = self._get_local_tmpl_context()
195 c = self._get_local_tmpl_context()
195 c.custom_var = 'foobar'
196 c.custom_var = 'foobar'
196 self._register_global_c(c)
197 self._register_global_c(c)
197 return c
198 return c
198 """
199 """
199 raise NotImplementedError('Needs implementation in view class')
200 raise NotImplementedError('Needs implementation in view class')
200
201
201
202
202 class RepoAppView(BaseAppView):
203 class RepoAppView(BaseAppView):
203
204
204 def __init__(self, context, request):
205 def __init__(self, context, request):
205 super(RepoAppView, self).__init__(context, request)
206 super(RepoAppView, self).__init__(context, request)
206 self.db_repo = request.db_repo
207 self.db_repo = request.db_repo
207 self.db_repo_name = self.db_repo.repo_name
208 self.db_repo_name = self.db_repo.repo_name
208 self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo)
209 self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo)
209
210
210 def _handle_missing_requirements(self, error):
211 def _handle_missing_requirements(self, error):
211 log.error(
212 log.error(
212 'Requirements are missing for repository %s: %s',
213 'Requirements are missing for repository %s: %s',
213 self.db_repo_name, error.message)
214 self.db_repo_name, error.message)
214
215
215 def _get_local_tmpl_context(self, include_app_defaults=False):
216 def _get_local_tmpl_context(self, include_app_defaults=False):
216 _ = self.request.translate
217 _ = self.request.translate
217 c = super(RepoAppView, self)._get_local_tmpl_context(
218 c = super(RepoAppView, self)._get_local_tmpl_context(
218 include_app_defaults=include_app_defaults)
219 include_app_defaults=include_app_defaults)
219
220
220 # register common vars for this type of view
221 # register common vars for this type of view
221 c.rhodecode_db_repo = self.db_repo
222 c.rhodecode_db_repo = self.db_repo
222 c.repo_name = self.db_repo_name
223 c.repo_name = self.db_repo_name
223 c.repository_pull_requests = self.db_repo_pull_requests
224 c.repository_pull_requests = self.db_repo_pull_requests
224
225
225 c.repository_requirements_missing = False
226 c.repository_requirements_missing = False
226 try:
227 try:
227 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
228 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
228 except RepositoryRequirementError as e:
229 except RepositoryRequirementError as e:
229 c.repository_requirements_missing = True
230 c.repository_requirements_missing = True
230 self._handle_missing_requirements(e)
231 self._handle_missing_requirements(e)
231 self.rhodecode_vcs_repo = None
232 self.rhodecode_vcs_repo = None
232
233
233 if (not c.repository_requirements_missing
234 if (not c.repository_requirements_missing
234 and self.rhodecode_vcs_repo is None):
235 and self.rhodecode_vcs_repo is None):
235 # unable to fetch this repo as vcs instance, report back to user
236 # unable to fetch this repo as vcs instance, report back to user
236 h.flash(_(
237 h.flash(_(
237 "The repository `%(repo_name)s` cannot be loaded in filesystem. "
238 "The repository `%(repo_name)s` cannot be loaded in filesystem. "
238 "Please check if it exist, or is not damaged.") %
239 "Please check if it exist, or is not damaged.") %
239 {'repo_name': c.repo_name},
240 {'repo_name': c.repo_name},
240 category='error', ignore_duplicate=True)
241 category='error', ignore_duplicate=True)
241 raise HTTPFound(h.route_path('home'))
242 raise HTTPFound(h.route_path('home'))
242
243
243 return c
244 return c
244
245
245 def _get_f_path(self, matchdict, default=None):
246 def _get_f_path(self, matchdict, default=None):
246 f_path = matchdict.get('f_path')
247 f_path = matchdict.get('f_path')
247 if f_path:
248 if f_path:
248 # fix for multiple initial slashes that causes errors for GIT
249 # fix for multiple initial slashes that causes errors for GIT
249 return f_path.lstrip('/')
250 return f_path.lstrip('/')
250
251
251 return default
252 return default
252
253
253
254
254 class RepoGroupAppView(BaseAppView):
255 class RepoGroupAppView(BaseAppView):
255 def __init__(self, context, request):
256 def __init__(self, context, request):
256 super(RepoGroupAppView, self).__init__(context, request)
257 super(RepoGroupAppView, self).__init__(context, request)
257 self.db_repo_group = request.db_repo_group
258 self.db_repo_group = request.db_repo_group
258 self.db_repo_group_name = self.db_repo_group.group_name
259 self.db_repo_group_name = self.db_repo_group.group_name
259
260
260
261
261 class DataGridAppView(object):
262 class DataGridAppView(object):
262 """
263 """
263 Common class to have re-usable grid rendering components
264 Common class to have re-usable grid rendering components
264 """
265 """
265
266
266 def _extract_ordering(self, request, column_map=None):
267 def _extract_ordering(self, request, column_map=None):
267 column_map = column_map or {}
268 column_map = column_map or {}
268 column_index = safe_int(request.GET.get('order[0][column]'))
269 column_index = safe_int(request.GET.get('order[0][column]'))
269 order_dir = request.GET.get(
270 order_dir = request.GET.get(
270 'order[0][dir]', 'desc')
271 'order[0][dir]', 'desc')
271 order_by = request.GET.get(
272 order_by = request.GET.get(
272 'columns[%s][data][sort]' % column_index, 'name_raw')
273 'columns[%s][data][sort]' % column_index, 'name_raw')
273
274
274 # translate datatable to DB columns
275 # translate datatable to DB columns
275 order_by = column_map.get(order_by) or order_by
276 order_by = column_map.get(order_by) or order_by
276
277
277 search_q = request.GET.get('search[value]')
278 search_q = request.GET.get('search[value]')
278 return search_q, order_by, order_dir
279 return search_q, order_by, order_dir
279
280
280 def _extract_chunk(self, request):
281 def _extract_chunk(self, request):
281 start = safe_int(request.GET.get('start'), 0)
282 start = safe_int(request.GET.get('start'), 0)
282 length = safe_int(request.GET.get('length'), 25)
283 length = safe_int(request.GET.get('length'), 25)
283 draw = safe_int(request.GET.get('draw'))
284 draw = safe_int(request.GET.get('draw'))
284 return draw, start, length
285 return draw, start, length
285
286
287 def _get_order_col(self, order_by, model):
288 if isinstance(order_by, basestring):
289 try:
290 return operator.attrgetter(order_by)(model)
291 except AttributeError:
292 return None
293 else:
294 return order_by
295
286
296
287 class BaseReferencesView(RepoAppView):
297 class BaseReferencesView(RepoAppView):
288 """
298 """
289 Base for reference view for branches, tags and bookmarks.
299 Base for reference view for branches, tags and bookmarks.
290 """
300 """
291 def load_default_context(self):
301 def load_default_context(self):
292 c = self._get_local_tmpl_context()
302 c = self._get_local_tmpl_context()
293
303
294 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
304 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
295 c.repo_info = self.db_repo
305 c.repo_info = self.db_repo
296
306
297 self._register_global_c(c)
307 self._register_global_c(c)
298 return c
308 return c
299
309
300 def load_refs_context(self, ref_items, partials_template):
310 def load_refs_context(self, ref_items, partials_template):
301 _render = self.request.get_partial_renderer(partials_template)
311 _render = self.request.get_partial_renderer(partials_template)
302 pre_load = ["author", "date", "message"]
312 pre_load = ["author", "date", "message"]
303
313
304 is_svn = h.is_svn(self.rhodecode_vcs_repo)
314 is_svn = h.is_svn(self.rhodecode_vcs_repo)
305 is_hg = h.is_hg(self.rhodecode_vcs_repo)
315 is_hg = h.is_hg(self.rhodecode_vcs_repo)
306
316
307 format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
317 format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
308
318
309 closed_refs = {}
319 closed_refs = {}
310 if is_hg:
320 if is_hg:
311 closed_refs = self.rhodecode_vcs_repo.branches_closed
321 closed_refs = self.rhodecode_vcs_repo.branches_closed
312
322
313 data = []
323 data = []
314 for ref_name, commit_id in ref_items:
324 for ref_name, commit_id in ref_items:
315 commit = self.rhodecode_vcs_repo.get_commit(
325 commit = self.rhodecode_vcs_repo.get_commit(
316 commit_id=commit_id, pre_load=pre_load)
326 commit_id=commit_id, pre_load=pre_load)
317 closed = ref_name in closed_refs
327 closed = ref_name in closed_refs
318
328
319 # TODO: johbo: Unify generation of reference links
329 # TODO: johbo: Unify generation of reference links
320 use_commit_id = '/' in ref_name or is_svn
330 use_commit_id = '/' in ref_name or is_svn
321
331
322 if use_commit_id:
332 if use_commit_id:
323 files_url = h.route_path(
333 files_url = h.route_path(
324 'repo_files',
334 'repo_files',
325 repo_name=self.db_repo_name,
335 repo_name=self.db_repo_name,
326 f_path=ref_name if is_svn else '',
336 f_path=ref_name if is_svn else '',
327 commit_id=commit_id)
337 commit_id=commit_id)
328
338
329 else:
339 else:
330 files_url = h.route_path(
340 files_url = h.route_path(
331 'repo_files',
341 'repo_files',
332 repo_name=self.db_repo_name,
342 repo_name=self.db_repo_name,
333 f_path=ref_name if is_svn else '',
343 f_path=ref_name if is_svn else '',
334 commit_id=ref_name,
344 commit_id=ref_name,
335 _query=dict(at=ref_name))
345 _query=dict(at=ref_name))
336
346
337 data.append({
347 data.append({
338 "name": _render('name', ref_name, files_url, closed),
348 "name": _render('name', ref_name, files_url, closed),
339 "name_raw": ref_name,
349 "name_raw": ref_name,
340 "date": _render('date', commit.date),
350 "date": _render('date', commit.date),
341 "date_raw": datetime_to_time(commit.date),
351 "date_raw": datetime_to_time(commit.date),
342 "author": _render('author', commit.author),
352 "author": _render('author', commit.author),
343 "commit": _render(
353 "commit": _render(
344 'commit', commit.message, commit.raw_id, commit.idx),
354 'commit', commit.message, commit.raw_id, commit.idx),
345 "commit_raw": commit.idx,
355 "commit_raw": commit.idx,
346 "compare": _render(
356 "compare": _render(
347 'compare', format_ref_id(ref_name, commit.raw_id)),
357 'compare', format_ref_id(ref_name, commit.raw_id)),
348 })
358 })
349
359
350 return data
360 return data
351
361
352
362
353 class RepoRoutePredicate(object):
363 class RepoRoutePredicate(object):
354 def __init__(self, val, config):
364 def __init__(self, val, config):
355 self.val = val
365 self.val = val
356
366
357 def text(self):
367 def text(self):
358 return 'repo_route = %s' % self.val
368 return 'repo_route = %s' % self.val
359
369
360 phash = text
370 phash = text
361
371
362 def __call__(self, info, request):
372 def __call__(self, info, request):
363
373
364 if hasattr(request, 'vcs_call'):
374 if hasattr(request, 'vcs_call'):
365 # skip vcs calls
375 # skip vcs calls
366 return
376 return
367
377
368 repo_name = info['match']['repo_name']
378 repo_name = info['match']['repo_name']
369 repo_model = repo.RepoModel()
379 repo_model = repo.RepoModel()
370 by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
380 by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
371
381
372 def redirect_if_creating(db_repo):
382 def redirect_if_creating(db_repo):
373 if db_repo.repo_state in [repo.Repository.STATE_PENDING]:
383 if db_repo.repo_state in [repo.Repository.STATE_PENDING]:
374 raise HTTPFound(
384 raise HTTPFound(
375 request.route_path('repo_creating',
385 request.route_path('repo_creating',
376 repo_name=db_repo.repo_name))
386 repo_name=db_repo.repo_name))
377
387
378 if by_name_match:
388 if by_name_match:
379 # register this as request object we can re-use later
389 # register this as request object we can re-use later
380 request.db_repo = by_name_match
390 request.db_repo = by_name_match
381 redirect_if_creating(by_name_match)
391 redirect_if_creating(by_name_match)
382 return True
392 return True
383
393
384 by_id_match = repo_model.get_repo_by_id(repo_name)
394 by_id_match = repo_model.get_repo_by_id(repo_name)
385 if by_id_match:
395 if by_id_match:
386 request.db_repo = by_id_match
396 request.db_repo = by_id_match
387 redirect_if_creating(by_id_match)
397 redirect_if_creating(by_id_match)
388 return True
398 return True
389
399
390 return False
400 return False
391
401
392
402
393 class RepoTypeRoutePredicate(object):
403 class RepoTypeRoutePredicate(object):
394 def __init__(self, val, config):
404 def __init__(self, val, config):
395 self.val = val or ['hg', 'git', 'svn']
405 self.val = val or ['hg', 'git', 'svn']
396
406
397 def text(self):
407 def text(self):
398 return 'repo_accepted_type = %s' % self.val
408 return 'repo_accepted_type = %s' % self.val
399
409
400 phash = text
410 phash = text
401
411
402 def __call__(self, info, request):
412 def __call__(self, info, request):
403 if hasattr(request, 'vcs_call'):
413 if hasattr(request, 'vcs_call'):
404 # skip vcs calls
414 # skip vcs calls
405 return
415 return
406
416
407 rhodecode_db_repo = request.db_repo
417 rhodecode_db_repo = request.db_repo
408
418
409 log.debug(
419 log.debug(
410 '%s checking repo type for %s in %s',
420 '%s checking repo type for %s in %s',
411 self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
421 self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
412
422
413 if rhodecode_db_repo.repo_type in self.val:
423 if rhodecode_db_repo.repo_type in self.val:
414 return True
424 return True
415 else:
425 else:
416 log.warning('Current view is not supported for repo type:%s',
426 log.warning('Current view is not supported for repo type:%s',
417 rhodecode_db_repo.repo_type)
427 rhodecode_db_repo.repo_type)
418 #
428 #
419 # h.flash(h.literal(
429 # h.flash(h.literal(
420 # _('Action not supported for %s.' % rhodecode_repo.alias)),
430 # _('Action not supported for %s.' % rhodecode_repo.alias)),
421 # category='warning')
431 # category='warning')
422 # return redirect(
432 # return redirect(
423 # route_path('repo_summary', repo_name=cls.rhodecode_db_repo.repo_name))
433 # route_path('repo_summary', repo_name=cls.rhodecode_db_repo.repo_name))
424
434
425 return False
435 return False
426
436
427
437
428 class RepoGroupRoutePredicate(object):
438 class RepoGroupRoutePredicate(object):
429 def __init__(self, val, config):
439 def __init__(self, val, config):
430 self.val = val
440 self.val = val
431
441
432 def text(self):
442 def text(self):
433 return 'repo_group_route = %s' % self.val
443 return 'repo_group_route = %s' % self.val
434
444
435 phash = text
445 phash = text
436
446
437 def __call__(self, info, request):
447 def __call__(self, info, request):
438 if hasattr(request, 'vcs_call'):
448 if hasattr(request, 'vcs_call'):
439 # skip vcs calls
449 # skip vcs calls
440 return
450 return
441
451
442 repo_group_name = info['match']['repo_group_name']
452 repo_group_name = info['match']['repo_group_name']
443 repo_group_model = repo_group.RepoGroupModel()
453 repo_group_model = repo_group.RepoGroupModel()
444 by_name_match = repo_group_model.get_by_group_name(
454 by_name_match = repo_group_model.get_by_group_name(
445 repo_group_name, cache=True)
455 repo_group_name, cache=True)
446
456
447 if by_name_match:
457 if by_name_match:
448 # register this as request object we can re-use later
458 # register this as request object we can re-use later
449 request.db_repo_group = by_name_match
459 request.db_repo_group = by_name_match
450 return True
460 return True
451
461
452 return False
462 return False
453
463
454
464
455 def includeme(config):
465 def includeme(config):
456 config.add_route_predicate(
466 config.add_route_predicate(
457 'repo_route', RepoRoutePredicate)
467 'repo_route', RepoRoutePredicate)
458 config.add_route_predicate(
468 config.add_route_predicate(
459 'repo_accepted_types', RepoTypeRoutePredicate)
469 'repo_accepted_types', RepoTypeRoutePredicate)
460 config.add_route_predicate(
470 config.add_route_predicate(
461 'repo_group_route', RepoGroupRoutePredicate)
471 'repo_group_route', RepoGroupRoutePredicate)
General Comments 0
You need to be logged in to leave comments. Login now