##// END OF EJS Templates
pyramid: turn on inclusion of app defaults. This will be required...
marcink -
r2332:332b2dd3 default
parent child Browse files
Show More
@@ -1,584 +1,582 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 import operator
24
24
25 from pyramid.httpexceptions import HTTPFound
25 from pyramid.httpexceptions import HTTPFound
26
26
27 from rhodecode.lib import helpers as h
27 from rhodecode.lib import helpers as h
28 from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time
28 from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time
29 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
29 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
30 from rhodecode.model import repo
30 from rhodecode.model import repo
31 from rhodecode.model import repo_group
31 from rhodecode.model import repo_group
32 from rhodecode.model import user_group
32 from rhodecode.model import user_group
33 from rhodecode.model import user
33 from rhodecode.model import user
34 from rhodecode.model.db import User
34 from rhodecode.model.db import User
35 from rhodecode.model.scm import ScmModel
35 from rhodecode.model.scm import ScmModel
36
36
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
39
39
40 ADMIN_PREFIX = '/_admin'
40 ADMIN_PREFIX = '/_admin'
41 STATIC_FILE_PREFIX = '/_static'
41 STATIC_FILE_PREFIX = '/_static'
42
42
43 URL_NAME_REQUIREMENTS = {
43 URL_NAME_REQUIREMENTS = {
44 # group name can have a slash in them, but they must not end with a slash
44 # group name can have a slash in them, but they must not end with a slash
45 'group_name': r'.*?[^/]',
45 'group_name': r'.*?[^/]',
46 'repo_group_name': r'.*?[^/]',
46 'repo_group_name': r'.*?[^/]',
47 # repo names can have a slash in them, but they must not end with a slash
47 # repo names can have a slash in them, but they must not end with a slash
48 'repo_name': r'.*?[^/]',
48 'repo_name': r'.*?[^/]',
49 # file path eats up everything at the end
49 # file path eats up everything at the end
50 'f_path': r'.*',
50 'f_path': r'.*',
51 # reference types
51 # reference types
52 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
52 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
53 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
53 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
54 }
54 }
55
55
56
56
57 def add_route_with_slash(config,name, pattern, **kw):
57 def add_route_with_slash(config,name, pattern, **kw):
58 config.add_route(name, pattern, **kw)
58 config.add_route(name, pattern, **kw)
59 if not pattern.endswith('/'):
59 if not pattern.endswith('/'):
60 config.add_route(name + '_slash', pattern + '/', **kw)
60 config.add_route(name + '_slash', pattern + '/', **kw)
61
61
62
62
63 def add_route_requirements(route_path, requirements=URL_NAME_REQUIREMENTS):
63 def add_route_requirements(route_path, requirements=URL_NAME_REQUIREMENTS):
64 """
64 """
65 Adds regex requirements to pyramid routes using a mapping dict
65 Adds regex requirements to pyramid routes using a mapping dict
66 e.g::
66 e.g::
67 add_route_requirements('{repo_name}/settings')
67 add_route_requirements('{repo_name}/settings')
68 """
68 """
69 for key, regex in requirements.items():
69 for key, regex in requirements.items():
70 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
70 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
71 return route_path
71 return route_path
72
72
73
73
74 def get_format_ref_id(repo):
74 def get_format_ref_id(repo):
75 """Returns a `repo` specific reference formatter function"""
75 """Returns a `repo` specific reference formatter function"""
76 if h.is_svn(repo):
76 if h.is_svn(repo):
77 return _format_ref_id_svn
77 return _format_ref_id_svn
78 else:
78 else:
79 return _format_ref_id
79 return _format_ref_id
80
80
81
81
82 def _format_ref_id(name, raw_id):
82 def _format_ref_id(name, raw_id):
83 """Default formatting of a given reference `name`"""
83 """Default formatting of a given reference `name`"""
84 return name
84 return name
85
85
86
86
87 def _format_ref_id_svn(name, raw_id):
87 def _format_ref_id_svn(name, raw_id):
88 """Special way of formatting a reference for Subversion including path"""
88 """Special way of formatting a reference for Subversion including path"""
89 return '%s@%s' % (name, raw_id)
89 return '%s@%s' % (name, raw_id)
90
90
91
91
92 class TemplateArgs(StrictAttributeDict):
92 class TemplateArgs(StrictAttributeDict):
93 pass
93 pass
94
94
95
95
96 class BaseAppView(object):
96 class BaseAppView(object):
97
97
98 def __init__(self, context, request):
98 def __init__(self, context, request):
99 self.request = request
99 self.request = request
100 self.context = context
100 self.context = context
101 self.session = request.session
101 self.session = request.session
102 self._rhodecode_user = request.user # auth user
102 self._rhodecode_user = request.user # auth user
103 self._rhodecode_db_user = self._rhodecode_user.get_instance()
103 self._rhodecode_db_user = self._rhodecode_user.get_instance()
104 self._maybe_needs_password_change(
104 self._maybe_needs_password_change(
105 request.matched_route.name, self._rhodecode_db_user)
105 request.matched_route.name, self._rhodecode_db_user)
106
106
107 def _maybe_needs_password_change(self, view_name, user_obj):
107 def _maybe_needs_password_change(self, view_name, user_obj):
108 log.debug('Checking if user %s needs password change on view %s',
108 log.debug('Checking if user %s needs password change on view %s',
109 user_obj, view_name)
109 user_obj, view_name)
110 skip_user_views = [
110 skip_user_views = [
111 'logout', 'login',
111 'logout', 'login',
112 'my_account_password', 'my_account_password_update'
112 'my_account_password', 'my_account_password_update'
113 ]
113 ]
114
114
115 if not user_obj:
115 if not user_obj:
116 return
116 return
117
117
118 if user_obj.username == User.DEFAULT_USER:
118 if user_obj.username == User.DEFAULT_USER:
119 return
119 return
120
120
121 now = time.time()
121 now = time.time()
122 should_change = user_obj.user_data.get('force_password_change')
122 should_change = user_obj.user_data.get('force_password_change')
123 change_after = safe_int(should_change) or 0
123 change_after = safe_int(should_change) or 0
124 if should_change and now > change_after:
124 if should_change and now > change_after:
125 log.debug('User %s requires password change', user_obj)
125 log.debug('User %s requires password change', user_obj)
126 h.flash('You are required to change your password', 'warning',
126 h.flash('You are required to change your password', 'warning',
127 ignore_duplicate=True)
127 ignore_duplicate=True)
128
128
129 if view_name not in skip_user_views:
129 if view_name not in skip_user_views:
130 raise HTTPFound(
130 raise HTTPFound(
131 self.request.route_path('my_account_password'))
131 self.request.route_path('my_account_password'))
132
132
133 def _log_creation_exception(self, e, repo_name):
133 def _log_creation_exception(self, e, repo_name):
134 _ = self.request.translate
134 _ = self.request.translate
135 reason = None
135 reason = None
136 if len(e.args) == 2:
136 if len(e.args) == 2:
137 reason = e.args[1]
137 reason = e.args[1]
138
138
139 if reason == 'INVALID_CERTIFICATE':
139 if reason == 'INVALID_CERTIFICATE':
140 log.exception(
140 log.exception(
141 'Exception creating a repository: invalid certificate')
141 'Exception creating a repository: invalid certificate')
142 msg = (_('Error creating repository %s: invalid certificate')
142 msg = (_('Error creating repository %s: invalid certificate')
143 % repo_name)
143 % repo_name)
144 else:
144 else:
145 log.exception("Exception creating a repository")
145 log.exception("Exception creating a repository")
146 msg = (_('Error creating repository %s')
146 msg = (_('Error creating repository %s')
147 % repo_name)
147 % repo_name)
148 return msg
148 return msg
149
149
150 def _get_local_tmpl_context(self, include_app_defaults=False):
150 def _get_local_tmpl_context(self, include_app_defaults=True):
151 c = TemplateArgs()
151 c = TemplateArgs()
152 c.auth_user = self.request.user
152 c.auth_user = self.request.user
153 # TODO(marcink): migrate the usage of c.rhodecode_user to c.auth_user
153 # TODO(marcink): migrate the usage of c.rhodecode_user to c.auth_user
154 c.rhodecode_user = self.request.user
154 c.rhodecode_user = self.request.user
155
155
156 if include_app_defaults:
156 if include_app_defaults:
157 # NOTE(marcink): after full pyramid migration include_app_defaults
158 # should be turned on by default
159 from rhodecode.lib.base import attach_context_attributes
157 from rhodecode.lib.base import attach_context_attributes
160 attach_context_attributes(c, self.request, self.request.user.user_id)
158 attach_context_attributes(c, self.request, self.request.user.user_id)
161
159
162 return c
160 return c
163
161
164 def _register_global_c(self, tmpl_args):
162 def _register_global_c(self, tmpl_args):
165 """
163 """
166 Registers attributes to pylons global `c`
164 Registers attributes to pylons global `c`
167 """
165 """
168
166
169 # TODO(marcink): remove once pyramid migration is finished
167 # TODO(marcink): remove once pyramid migration is finished
170 from pylons import tmpl_context as c
168 from pylons import tmpl_context as c
171 try:
169 try:
172 for k, v in tmpl_args.items():
170 for k, v in tmpl_args.items():
173 setattr(c, k, v)
171 setattr(c, k, v)
174 except TypeError:
172 except TypeError:
175 log.exception('Failed to register pylons C')
173 log.exception('Failed to register pylons C')
176 pass
174 pass
177
175
178 def _get_template_context(self, tmpl_args):
176 def _get_template_context(self, tmpl_args):
179 self._register_global_c(tmpl_args)
177 self._register_global_c(tmpl_args)
180
178
181 local_tmpl_args = {
179 local_tmpl_args = {
182 'defaults': {},
180 'defaults': {},
183 'errors': {},
181 'errors': {},
184 # 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
185 # 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'
186 # make sure we replace usage of _c in templates too
184 # make sure we replace usage of _c in templates too
187 '_c': tmpl_args
185 '_c': tmpl_args
188 }
186 }
189 local_tmpl_args.update(tmpl_args)
187 local_tmpl_args.update(tmpl_args)
190 return local_tmpl_args
188 return local_tmpl_args
191
189
192 def load_default_context(self):
190 def load_default_context(self):
193 """
191 """
194 example:
192 example:
195
193
196 def load_default_context(self):
194 def load_default_context(self):
197 c = self._get_local_tmpl_context()
195 c = self._get_local_tmpl_context()
198 c.custom_var = 'foobar'
196 c.custom_var = 'foobar'
199 self._register_global_c(c)
197 self._register_global_c(c)
200 return c
198 return c
201 """
199 """
202 raise NotImplementedError('Needs implementation in view class')
200 raise NotImplementedError('Needs implementation in view class')
203
201
204
202
205 class RepoAppView(BaseAppView):
203 class RepoAppView(BaseAppView):
206
204
207 def __init__(self, context, request):
205 def __init__(self, context, request):
208 super(RepoAppView, self).__init__(context, request)
206 super(RepoAppView, self).__init__(context, request)
209 self.db_repo = request.db_repo
207 self.db_repo = request.db_repo
210 self.db_repo_name = self.db_repo.repo_name
208 self.db_repo_name = self.db_repo.repo_name
211 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)
212
210
213 def _handle_missing_requirements(self, error):
211 def _handle_missing_requirements(self, error):
214 log.error(
212 log.error(
215 'Requirements are missing for repository %s: %s',
213 'Requirements are missing for repository %s: %s',
216 self.db_repo_name, error.message)
214 self.db_repo_name, error.message)
217
215
218 def _get_local_tmpl_context(self, include_app_defaults=False):
216 def _get_local_tmpl_context(self, include_app_defaults=False):
219 _ = self.request.translate
217 _ = self.request.translate
220 c = super(RepoAppView, self)._get_local_tmpl_context(
218 c = super(RepoAppView, self)._get_local_tmpl_context(
221 include_app_defaults=include_app_defaults)
219 include_app_defaults=include_app_defaults)
222
220
223 # register common vars for this type of view
221 # register common vars for this type of view
224 c.rhodecode_db_repo = self.db_repo
222 c.rhodecode_db_repo = self.db_repo
225 c.repo_name = self.db_repo_name
223 c.repo_name = self.db_repo_name
226 c.repository_pull_requests = self.db_repo_pull_requests
224 c.repository_pull_requests = self.db_repo_pull_requests
227
225
228 c.repository_requirements_missing = False
226 c.repository_requirements_missing = False
229 try:
227 try:
230 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
228 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
231 except RepositoryRequirementError as e:
229 except RepositoryRequirementError as e:
232 c.repository_requirements_missing = True
230 c.repository_requirements_missing = True
233 self._handle_missing_requirements(e)
231 self._handle_missing_requirements(e)
234 self.rhodecode_vcs_repo = None
232 self.rhodecode_vcs_repo = None
235
233
236 if (not c.repository_requirements_missing
234 if (not c.repository_requirements_missing
237 and self.rhodecode_vcs_repo is None):
235 and self.rhodecode_vcs_repo is None):
238 # 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
239 h.flash(_(
237 h.flash(_(
240 "The repository `%(repo_name)s` cannot be loaded in filesystem. "
238 "The repository `%(repo_name)s` cannot be loaded in filesystem. "
241 "Please check if it exist, or is not damaged.") %
239 "Please check if it exist, or is not damaged.") %
242 {'repo_name': c.repo_name},
240 {'repo_name': c.repo_name},
243 category='error', ignore_duplicate=True)
241 category='error', ignore_duplicate=True)
244 raise HTTPFound(h.route_path('home'))
242 raise HTTPFound(h.route_path('home'))
245
243
246 return c
244 return c
247
245
248 def _get_f_path(self, matchdict, default=None):
246 def _get_f_path(self, matchdict, default=None):
249 f_path = matchdict.get('f_path')
247 f_path = matchdict.get('f_path')
250 if f_path:
248 if f_path:
251 # fix for multiple initial slashes that causes errors for GIT
249 # fix for multiple initial slashes that causes errors for GIT
252 return f_path.lstrip('/')
250 return f_path.lstrip('/')
253
251
254 return default
252 return default
255
253
256
254
257 class RepoGroupAppView(BaseAppView):
255 class RepoGroupAppView(BaseAppView):
258 def __init__(self, context, request):
256 def __init__(self, context, request):
259 super(RepoGroupAppView, self).__init__(context, request)
257 super(RepoGroupAppView, self).__init__(context, request)
260 self.db_repo_group = request.db_repo_group
258 self.db_repo_group = request.db_repo_group
261 self.db_repo_group_name = self.db_repo_group.group_name
259 self.db_repo_group_name = self.db_repo_group.group_name
262
260
263 def _revoke_perms_on_yourself(self, form_result):
261 def _revoke_perms_on_yourself(self, form_result):
264 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
262 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
265 form_result['perm_updates'])
263 form_result['perm_updates'])
266 _additions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
264 _additions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
267 form_result['perm_additions'])
265 form_result['perm_additions'])
268 _deletions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
266 _deletions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
269 form_result['perm_deletions'])
267 form_result['perm_deletions'])
270 admin_perm = 'group.admin'
268 admin_perm = 'group.admin'
271 if _updates and _updates[0][1] != admin_perm or \
269 if _updates and _updates[0][1] != admin_perm or \
272 _additions and _additions[0][1] != admin_perm or \
270 _additions and _additions[0][1] != admin_perm or \
273 _deletions and _deletions[0][1] != admin_perm:
271 _deletions and _deletions[0][1] != admin_perm:
274 return True
272 return True
275 return False
273 return False
276
274
277
275
278 class UserGroupAppView(BaseAppView):
276 class UserGroupAppView(BaseAppView):
279 def __init__(self, context, request):
277 def __init__(self, context, request):
280 super(UserGroupAppView, self).__init__(context, request)
278 super(UserGroupAppView, self).__init__(context, request)
281 self.db_user_group = request.db_user_group
279 self.db_user_group = request.db_user_group
282 self.db_user_group_name = self.db_user_group.users_group_name
280 self.db_user_group_name = self.db_user_group.users_group_name
283
281
284
282
285 class UserAppView(BaseAppView):
283 class UserAppView(BaseAppView):
286 def __init__(self, context, request):
284 def __init__(self, context, request):
287 super(UserAppView, self).__init__(context, request)
285 super(UserAppView, self).__init__(context, request)
288 self.db_user = request.db_user
286 self.db_user = request.db_user
289 self.db_user_id = self.db_user.user_id
287 self.db_user_id = self.db_user.user_id
290
288
291 _ = self.request.translate
289 _ = self.request.translate
292 if not request.db_user_supports_default:
290 if not request.db_user_supports_default:
293 if self.db_user.username == User.DEFAULT_USER:
291 if self.db_user.username == User.DEFAULT_USER:
294 h.flash(_("Editing user `{}` is disabled.".format(
292 h.flash(_("Editing user `{}` is disabled.".format(
295 User.DEFAULT_USER)), category='warning')
293 User.DEFAULT_USER)), category='warning')
296 raise HTTPFound(h.route_path('users'))
294 raise HTTPFound(h.route_path('users'))
297
295
298
296
299 class DataGridAppView(object):
297 class DataGridAppView(object):
300 """
298 """
301 Common class to have re-usable grid rendering components
299 Common class to have re-usable grid rendering components
302 """
300 """
303
301
304 def _extract_ordering(self, request, column_map=None):
302 def _extract_ordering(self, request, column_map=None):
305 column_map = column_map or {}
303 column_map = column_map or {}
306 column_index = safe_int(request.GET.get('order[0][column]'))
304 column_index = safe_int(request.GET.get('order[0][column]'))
307 order_dir = request.GET.get(
305 order_dir = request.GET.get(
308 'order[0][dir]', 'desc')
306 'order[0][dir]', 'desc')
309 order_by = request.GET.get(
307 order_by = request.GET.get(
310 'columns[%s][data][sort]' % column_index, 'name_raw')
308 'columns[%s][data][sort]' % column_index, 'name_raw')
311
309
312 # translate datatable to DB columns
310 # translate datatable to DB columns
313 order_by = column_map.get(order_by) or order_by
311 order_by = column_map.get(order_by) or order_by
314
312
315 search_q = request.GET.get('search[value]')
313 search_q = request.GET.get('search[value]')
316 return search_q, order_by, order_dir
314 return search_q, order_by, order_dir
317
315
318 def _extract_chunk(self, request):
316 def _extract_chunk(self, request):
319 start = safe_int(request.GET.get('start'), 0)
317 start = safe_int(request.GET.get('start'), 0)
320 length = safe_int(request.GET.get('length'), 25)
318 length = safe_int(request.GET.get('length'), 25)
321 draw = safe_int(request.GET.get('draw'))
319 draw = safe_int(request.GET.get('draw'))
322 return draw, start, length
320 return draw, start, length
323
321
324 def _get_order_col(self, order_by, model):
322 def _get_order_col(self, order_by, model):
325 if isinstance(order_by, basestring):
323 if isinstance(order_by, basestring):
326 try:
324 try:
327 return operator.attrgetter(order_by)(model)
325 return operator.attrgetter(order_by)(model)
328 except AttributeError:
326 except AttributeError:
329 return None
327 return None
330 else:
328 else:
331 return order_by
329 return order_by
332
330
333
331
334 class BaseReferencesView(RepoAppView):
332 class BaseReferencesView(RepoAppView):
335 """
333 """
336 Base for reference view for branches, tags and bookmarks.
334 Base for reference view for branches, tags and bookmarks.
337 """
335 """
338 def load_default_context(self):
336 def load_default_context(self):
339 c = self._get_local_tmpl_context()
337 c = self._get_local_tmpl_context()
340
338
341 self._register_global_c(c)
339 self._register_global_c(c)
342 return c
340 return c
343
341
344 def load_refs_context(self, ref_items, partials_template):
342 def load_refs_context(self, ref_items, partials_template):
345 _render = self.request.get_partial_renderer(partials_template)
343 _render = self.request.get_partial_renderer(partials_template)
346 pre_load = ["author", "date", "message"]
344 pre_load = ["author", "date", "message"]
347
345
348 is_svn = h.is_svn(self.rhodecode_vcs_repo)
346 is_svn = h.is_svn(self.rhodecode_vcs_repo)
349 is_hg = h.is_hg(self.rhodecode_vcs_repo)
347 is_hg = h.is_hg(self.rhodecode_vcs_repo)
350
348
351 format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
349 format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
352
350
353 closed_refs = {}
351 closed_refs = {}
354 if is_hg:
352 if is_hg:
355 closed_refs = self.rhodecode_vcs_repo.branches_closed
353 closed_refs = self.rhodecode_vcs_repo.branches_closed
356
354
357 data = []
355 data = []
358 for ref_name, commit_id in ref_items:
356 for ref_name, commit_id in ref_items:
359 commit = self.rhodecode_vcs_repo.get_commit(
357 commit = self.rhodecode_vcs_repo.get_commit(
360 commit_id=commit_id, pre_load=pre_load)
358 commit_id=commit_id, pre_load=pre_load)
361 closed = ref_name in closed_refs
359 closed = ref_name in closed_refs
362
360
363 # TODO: johbo: Unify generation of reference links
361 # TODO: johbo: Unify generation of reference links
364 use_commit_id = '/' in ref_name or is_svn
362 use_commit_id = '/' in ref_name or is_svn
365
363
366 if use_commit_id:
364 if use_commit_id:
367 files_url = h.route_path(
365 files_url = h.route_path(
368 'repo_files',
366 'repo_files',
369 repo_name=self.db_repo_name,
367 repo_name=self.db_repo_name,
370 f_path=ref_name if is_svn else '',
368 f_path=ref_name if is_svn else '',
371 commit_id=commit_id)
369 commit_id=commit_id)
372
370
373 else:
371 else:
374 files_url = h.route_path(
372 files_url = h.route_path(
375 'repo_files',
373 'repo_files',
376 repo_name=self.db_repo_name,
374 repo_name=self.db_repo_name,
377 f_path=ref_name if is_svn else '',
375 f_path=ref_name if is_svn else '',
378 commit_id=ref_name,
376 commit_id=ref_name,
379 _query=dict(at=ref_name))
377 _query=dict(at=ref_name))
380
378
381 data.append({
379 data.append({
382 "name": _render('name', ref_name, files_url, closed),
380 "name": _render('name', ref_name, files_url, closed),
383 "name_raw": ref_name,
381 "name_raw": ref_name,
384 "date": _render('date', commit.date),
382 "date": _render('date', commit.date),
385 "date_raw": datetime_to_time(commit.date),
383 "date_raw": datetime_to_time(commit.date),
386 "author": _render('author', commit.author),
384 "author": _render('author', commit.author),
387 "commit": _render(
385 "commit": _render(
388 'commit', commit.message, commit.raw_id, commit.idx),
386 'commit', commit.message, commit.raw_id, commit.idx),
389 "commit_raw": commit.idx,
387 "commit_raw": commit.idx,
390 "compare": _render(
388 "compare": _render(
391 'compare', format_ref_id(ref_name, commit.raw_id)),
389 'compare', format_ref_id(ref_name, commit.raw_id)),
392 })
390 })
393
391
394 return data
392 return data
395
393
396
394
397 class RepoRoutePredicate(object):
395 class RepoRoutePredicate(object):
398 def __init__(self, val, config):
396 def __init__(self, val, config):
399 self.val = val
397 self.val = val
400
398
401 def text(self):
399 def text(self):
402 return 'repo_route = %s' % self.val
400 return 'repo_route = %s' % self.val
403
401
404 phash = text
402 phash = text
405
403
406 def __call__(self, info, request):
404 def __call__(self, info, request):
407
405
408 if hasattr(request, 'vcs_call'):
406 if hasattr(request, 'vcs_call'):
409 # skip vcs calls
407 # skip vcs calls
410 return
408 return
411
409
412 repo_name = info['match']['repo_name']
410 repo_name = info['match']['repo_name']
413 repo_model = repo.RepoModel()
411 repo_model = repo.RepoModel()
414 by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
412 by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
415
413
416 def redirect_if_creating(db_repo):
414 def redirect_if_creating(db_repo):
417 if db_repo.repo_state in [repo.Repository.STATE_PENDING]:
415 if db_repo.repo_state in [repo.Repository.STATE_PENDING]:
418 raise HTTPFound(
416 raise HTTPFound(
419 request.route_path('repo_creating',
417 request.route_path('repo_creating',
420 repo_name=db_repo.repo_name))
418 repo_name=db_repo.repo_name))
421
419
422 if by_name_match:
420 if by_name_match:
423 # register this as request object we can re-use later
421 # register this as request object we can re-use later
424 request.db_repo = by_name_match
422 request.db_repo = by_name_match
425 redirect_if_creating(by_name_match)
423 redirect_if_creating(by_name_match)
426 return True
424 return True
427
425
428 by_id_match = repo_model.get_repo_by_id(repo_name)
426 by_id_match = repo_model.get_repo_by_id(repo_name)
429 if by_id_match:
427 if by_id_match:
430 request.db_repo = by_id_match
428 request.db_repo = by_id_match
431 redirect_if_creating(by_id_match)
429 redirect_if_creating(by_id_match)
432 return True
430 return True
433
431
434 return False
432 return False
435
433
436
434
437 class RepoTypeRoutePredicate(object):
435 class RepoTypeRoutePredicate(object):
438 def __init__(self, val, config):
436 def __init__(self, val, config):
439 self.val = val or ['hg', 'git', 'svn']
437 self.val = val or ['hg', 'git', 'svn']
440
438
441 def text(self):
439 def text(self):
442 return 'repo_accepted_type = %s' % self.val
440 return 'repo_accepted_type = %s' % self.val
443
441
444 phash = text
442 phash = text
445
443
446 def __call__(self, info, request):
444 def __call__(self, info, request):
447 if hasattr(request, 'vcs_call'):
445 if hasattr(request, 'vcs_call'):
448 # skip vcs calls
446 # skip vcs calls
449 return
447 return
450
448
451 rhodecode_db_repo = request.db_repo
449 rhodecode_db_repo = request.db_repo
452
450
453 log.debug(
451 log.debug(
454 '%s checking repo type for %s in %s',
452 '%s checking repo type for %s in %s',
455 self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
453 self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
456
454
457 if rhodecode_db_repo.repo_type in self.val:
455 if rhodecode_db_repo.repo_type in self.val:
458 return True
456 return True
459 else:
457 else:
460 log.warning('Current view is not supported for repo type:%s',
458 log.warning('Current view is not supported for repo type:%s',
461 rhodecode_db_repo.repo_type)
459 rhodecode_db_repo.repo_type)
462 #
460 #
463 # h.flash(h.literal(
461 # h.flash(h.literal(
464 # _('Action not supported for %s.' % rhodecode_repo.alias)),
462 # _('Action not supported for %s.' % rhodecode_repo.alias)),
465 # category='warning')
463 # category='warning')
466 # return redirect(
464 # return redirect(
467 # route_path('repo_summary', repo_name=cls.rhodecode_db_repo.repo_name))
465 # route_path('repo_summary', repo_name=cls.rhodecode_db_repo.repo_name))
468
466
469 return False
467 return False
470
468
471
469
472 class RepoGroupRoutePredicate(object):
470 class RepoGroupRoutePredicate(object):
473 def __init__(self, val, config):
471 def __init__(self, val, config):
474 self.val = val
472 self.val = val
475
473
476 def text(self):
474 def text(self):
477 return 'repo_group_route = %s' % self.val
475 return 'repo_group_route = %s' % self.val
478
476
479 phash = text
477 phash = text
480
478
481 def __call__(self, info, request):
479 def __call__(self, info, request):
482 if hasattr(request, 'vcs_call'):
480 if hasattr(request, 'vcs_call'):
483 # skip vcs calls
481 # skip vcs calls
484 return
482 return
485
483
486 repo_group_name = info['match']['repo_group_name']
484 repo_group_name = info['match']['repo_group_name']
487 repo_group_model = repo_group.RepoGroupModel()
485 repo_group_model = repo_group.RepoGroupModel()
488 by_name_match = repo_group_model.get_by_group_name(
486 by_name_match = repo_group_model.get_by_group_name(
489 repo_group_name, cache=True)
487 repo_group_name, cache=True)
490
488
491 if by_name_match:
489 if by_name_match:
492 # register this as request object we can re-use later
490 # register this as request object we can re-use later
493 request.db_repo_group = by_name_match
491 request.db_repo_group = by_name_match
494 return True
492 return True
495
493
496 return False
494 return False
497
495
498
496
499 class UserGroupRoutePredicate(object):
497 class UserGroupRoutePredicate(object):
500 def __init__(self, val, config):
498 def __init__(self, val, config):
501 self.val = val
499 self.val = val
502
500
503 def text(self):
501 def text(self):
504 return 'user_group_route = %s' % self.val
502 return 'user_group_route = %s' % self.val
505
503
506 phash = text
504 phash = text
507
505
508 def __call__(self, info, request):
506 def __call__(self, info, request):
509 if hasattr(request, 'vcs_call'):
507 if hasattr(request, 'vcs_call'):
510 # skip vcs calls
508 # skip vcs calls
511 return
509 return
512
510
513 user_group_id = info['match']['user_group_id']
511 user_group_id = info['match']['user_group_id']
514 user_group_model = user_group.UserGroup()
512 user_group_model = user_group.UserGroup()
515 by_id_match = user_group_model.get(
513 by_id_match = user_group_model.get(
516 user_group_id, cache=True)
514 user_group_id, cache=True)
517
515
518 if by_id_match:
516 if by_id_match:
519 # register this as request object we can re-use later
517 # register this as request object we can re-use later
520 request.db_user_group = by_id_match
518 request.db_user_group = by_id_match
521 return True
519 return True
522
520
523 return False
521 return False
524
522
525
523
526 class UserRoutePredicateBase(object):
524 class UserRoutePredicateBase(object):
527 supports_default = None
525 supports_default = None
528
526
529 def __init__(self, val, config):
527 def __init__(self, val, config):
530 self.val = val
528 self.val = val
531
529
532 def text(self):
530 def text(self):
533 raise NotImplementedError()
531 raise NotImplementedError()
534
532
535 def __call__(self, info, request):
533 def __call__(self, info, request):
536 if hasattr(request, 'vcs_call'):
534 if hasattr(request, 'vcs_call'):
537 # skip vcs calls
535 # skip vcs calls
538 return
536 return
539
537
540 user_id = info['match']['user_id']
538 user_id = info['match']['user_id']
541 user_model = user.User()
539 user_model = user.User()
542 by_id_match = user_model.get(
540 by_id_match = user_model.get(
543 user_id, cache=True)
541 user_id, cache=True)
544
542
545 if by_id_match:
543 if by_id_match:
546 # register this as request object we can re-use later
544 # register this as request object we can re-use later
547 request.db_user = by_id_match
545 request.db_user = by_id_match
548 request.db_user_supports_default = self.supports_default
546 request.db_user_supports_default = self.supports_default
549 return True
547 return True
550
548
551 return False
549 return False
552
550
553
551
554 class UserRoutePredicate(UserRoutePredicateBase):
552 class UserRoutePredicate(UserRoutePredicateBase):
555 supports_default = False
553 supports_default = False
556
554
557 def text(self):
555 def text(self):
558 return 'user_route = %s' % self.val
556 return 'user_route = %s' % self.val
559
557
560 phash = text
558 phash = text
561
559
562
560
563 class UserRouteWithDefaultPredicate(UserRoutePredicateBase):
561 class UserRouteWithDefaultPredicate(UserRoutePredicateBase):
564 supports_default = True
562 supports_default = True
565
563
566 def text(self):
564 def text(self):
567 return 'user_with_default_route = %s' % self.val
565 return 'user_with_default_route = %s' % self.val
568
566
569 phash = text
567 phash = text
570
568
571
569
572 def includeme(config):
570 def includeme(config):
573 config.add_route_predicate(
571 config.add_route_predicate(
574 'repo_route', RepoRoutePredicate)
572 'repo_route', RepoRoutePredicate)
575 config.add_route_predicate(
573 config.add_route_predicate(
576 'repo_accepted_types', RepoTypeRoutePredicate)
574 'repo_accepted_types', RepoTypeRoutePredicate)
577 config.add_route_predicate(
575 config.add_route_predicate(
578 'repo_group_route', RepoGroupRoutePredicate)
576 'repo_group_route', RepoGroupRoutePredicate)
579 config.add_route_predicate(
577 config.add_route_predicate(
580 'user_group_route', UserGroupRoutePredicate)
578 'user_group_route', UserGroupRoutePredicate)
581 config.add_route_predicate(
579 config.add_route_predicate(
582 'user_route_with_default', UserRouteWithDefaultPredicate)
580 'user_route_with_default', UserRouteWithDefaultPredicate)
583 config.add_route_predicate(
581 config.add_route_predicate(
584 'user_route', UserRoutePredicate) No newline at end of file
582 'user_route', UserRoutePredicate)
General Comments 0
You need to be logged in to leave comments. Login now