##// END OF EJS Templates
reviewers: moved the new v1 api of default reviewers into pyramid view....
marcink -
r1767:dee6c9db default
parent child Browse files
Show More
@@ -1,125 +1,129 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 def includeme(config):
23 23
24 24 # Summary
25 25 config.add_route(
26 26 name='repo_summary_explicit',
27 27 pattern='/{repo_name:.*?[^/]}/summary', repo_route=True)
28 28
29 29 # Tags
30 30 config.add_route(
31 31 name='tags_home',
32 32 pattern='/{repo_name:.*?[^/]}/tags', repo_route=True)
33 33
34 34 # Branches
35 35 config.add_route(
36 36 name='branches_home',
37 37 pattern='/{repo_name:.*?[^/]}/branches', repo_route=True)
38 38
39 39 # Bookmarks
40 40 config.add_route(
41 41 name='bookmarks_home',
42 42 pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True)
43 43
44 44 # Pull Requests
45 45 config.add_route(
46 46 name='pullrequest_show',
47 47 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id}',
48 48 repo_route=True)
49 49
50 50 config.add_route(
51 51 name='pullrequest_show_all',
52 52 pattern='/{repo_name:.*?[^/]}/pull-request',
53 53 repo_route=True, repo_accepted_types=['hg', 'git'])
54 54
55 55 config.add_route(
56 56 name='pullrequest_show_all_data',
57 57 pattern='/{repo_name:.*?[^/]}/pull-request-data',
58 58 repo_route=True, repo_accepted_types=['hg', 'git'])
59 59
60 60 # Settings
61 61 config.add_route(
62 62 name='edit_repo',
63 63 pattern='/{repo_name:.*?[^/]}/settings', repo_route=True)
64 64
65 65 # Settings advanced
66 66 config.add_route(
67 67 name='edit_repo_advanced',
68 68 pattern='/{repo_name:.*?[^/]}/settings/advanced', repo_route=True)
69 69 config.add_route(
70 70 name='edit_repo_advanced_delete',
71 71 pattern='/{repo_name:.*?[^/]}/settings/advanced/delete', repo_route=True)
72 72 config.add_route(
73 73 name='edit_repo_advanced_locking',
74 74 pattern='/{repo_name:.*?[^/]}/settings/advanced/locking', repo_route=True)
75 75 config.add_route(
76 76 name='edit_repo_advanced_journal',
77 77 pattern='/{repo_name:.*?[^/]}/settings/advanced/journal', repo_route=True)
78 78 config.add_route(
79 79 name='edit_repo_advanced_fork',
80 80 pattern='/{repo_name:.*?[^/]}/settings/advanced/fork', repo_route=True)
81 81
82 82 # Caches
83 83 config.add_route(
84 84 name='edit_repo_caches',
85 85 pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True)
86 86
87 87 # Permissions
88 88 config.add_route(
89 89 name='edit_repo_perms',
90 90 pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True)
91 91
92 92 # Repo Review Rules
93 93 config.add_route(
94 94 name='repo_reviewers',
95 95 pattern='/{repo_name:.*?[^/]}/settings/review/rules', repo_route=True)
96 96
97 config.add_route(
98 name='repo_default_reviewers_data',
99 pattern='/{repo_name:.*?[^/]}/settings/review/default-reviewers', repo_route=True)
100
97 101 # Maintenance
98 102 config.add_route(
99 103 name='repo_maintenance',
100 104 pattern='/{repo_name:.*?[^/]}/settings/maintenance', repo_route=True)
101 105
102 106 config.add_route(
103 107 name='repo_maintenance_execute',
104 108 pattern='/{repo_name:.*?[^/]}/settings/maintenance/execute', repo_route=True)
105 109
106 110 # Strip
107 111 config.add_route(
108 112 name='strip',
109 113 pattern='/{repo_name:.*?[^/]}/settings/strip', repo_route=True)
110 114
111 115 config.add_route(
112 116 name='strip_check',
113 117 pattern='/{repo_name:.*?[^/]}/settings/strip_check', repo_route=True)
114 118
115 119 config.add_route(
116 120 name='strip_execute',
117 121 pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True)
118 122
119 123 # NOTE(marcink): needs to be at the end for catch-all
120 124 # config.add_route(
121 125 # name='repo_summary',
122 126 # pattern='/{repo_name:.*?[^/]}', repo_route=True)
123 127
124 128 # Scan module for configuration decorators.
125 129 config.scan()
@@ -1,51 +1,69 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22
23 23 from pyramid.view import view_config
24 24
25 25 from rhodecode.apps._base import RepoAppView
26 from rhodecode.controllers import utils
26 27 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
27 28
28 29 log = logging.getLogger(__name__)
29 30
30 31
31 32 class RepoReviewRulesView(RepoAppView):
32 33 def load_default_context(self):
33 34 c = self._get_local_tmpl_context()
34 35
35 36 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
36 37 c.repo_info = self.db_repo
37 38
38 39 self._register_global_c(c)
39 40 return c
40 41
41 42 @LoginRequired()
42 43 @HasRepoPermissionAnyDecorator('repository.admin')
43 44 @view_config(
44 45 route_name='repo_reviewers', request_method='GET',
45 46 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
46 47 def repo_review_rules(self):
47 48 c = self.load_default_context()
48 49 c.active = 'reviewers'
49 50
50 51 return self._get_template_context(c)
51 52
53 @LoginRequired()
54 @HasRepoPermissionAnyDecorator(
55 'repository.read', 'repository.write', 'repository.admin')
56 @view_config(
57 route_name='repo_default_reviewers_data', request_method='GET',
58 renderer='json_ext')
59 def repo_default_reviewers_data(self):
60 reasons = ['Default reviewer', 'Repository owner']
61 default = utils.reviewer_as_json(
62 user=self.db_repo.user, reasons=reasons, mandatory=False)
63
64 return {
65 'api_ver': 'v1', # define version for later possible schema upgrade
66 'reviewers': [default],
67 'rules': {},
68 'rules_data': {},
69 }
@@ -1,1030 +1,1027 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Routes configuration
23 23
24 24 The more specific and detailed routes should be defined first so they
25 25 may take precedent over the more generic routes. For more information
26 26 refer to the routes manual at http://routes.groovie.org/docs/
27 27
28 28 IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py
29 29 and _route_name variable which uses some of stored naming here to do redirects.
30 30 """
31 31 import os
32 32 import re
33 33 from routes import Mapper
34 34
35 35 # prefix for non repository related links needs to be prefixed with `/`
36 36 ADMIN_PREFIX = '/_admin'
37 37 STATIC_FILE_PREFIX = '/_static'
38 38
39 39 # Default requirements for URL parts
40 40 URL_NAME_REQUIREMENTS = {
41 41 # group name can have a slash in them, but they must not end with a slash
42 42 'group_name': r'.*?[^/]',
43 43 'repo_group_name': r'.*?[^/]',
44 44 # repo names can have a slash in them, but they must not end with a slash
45 45 'repo_name': r'.*?[^/]',
46 46 # file path eats up everything at the end
47 47 'f_path': r'.*',
48 48 # reference types
49 49 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
50 50 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
51 51 }
52 52
53 53
54 54 def add_route_requirements(route_path, requirements):
55 55 """
56 56 Adds regex requirements to pyramid routes using a mapping dict
57 57
58 58 >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'})
59 59 '/{action}/{id:\d+}'
60 60
61 61 """
62 62 for key, regex in requirements.items():
63 63 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
64 64 return route_path
65 65
66 66
67 67 class JSRoutesMapper(Mapper):
68 68 """
69 69 Wrapper for routes.Mapper to make pyroutes compatible url definitions
70 70 """
71 71 _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
72 72 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
73 73 def __init__(self, *args, **kw):
74 74 super(JSRoutesMapper, self).__init__(*args, **kw)
75 75 self._jsroutes = []
76 76
77 77 def connect(self, *args, **kw):
78 78 """
79 79 Wrapper for connect to take an extra argument jsroute=True
80 80
81 81 :param jsroute: boolean, if True will add the route to the pyroutes list
82 82 """
83 83 if kw.pop('jsroute', False):
84 84 if not self._named_route_regex.match(args[0]):
85 85 raise Exception('only named routes can be added to pyroutes')
86 86 self._jsroutes.append(args[0])
87 87
88 88 super(JSRoutesMapper, self).connect(*args, **kw)
89 89
90 90 def _extract_route_information(self, route):
91 91 """
92 92 Convert a route into tuple(name, path, args), eg:
93 93 ('show_user', '/profile/%(username)s', ['username'])
94 94 """
95 95 routepath = route.routepath
96 96 def replace(matchobj):
97 97 if matchobj.group(1):
98 98 return "%%(%s)s" % matchobj.group(1).split(':')[0]
99 99 else:
100 100 return "%%(%s)s" % matchobj.group(2)
101 101
102 102 routepath = self._argument_prog.sub(replace, routepath)
103 103 return (
104 104 route.name,
105 105 routepath,
106 106 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
107 107 for arg in self._argument_prog.findall(route.routepath)]
108 108 )
109 109
110 110 def jsroutes(self):
111 111 """
112 112 Return a list of pyroutes.js compatible routes
113 113 """
114 114 for route_name in self._jsroutes:
115 115 yield self._extract_route_information(self._routenames[route_name])
116 116
117 117
118 118 def make_map(config):
119 119 """Create, configure and return the routes Mapper"""
120 120 rmap = JSRoutesMapper(directory=config['pylons.paths']['controllers'],
121 121 always_scan=config['debug'])
122 122 rmap.minimization = False
123 123 rmap.explicit = False
124 124
125 125 from rhodecode.lib.utils2 import str2bool
126 126 from rhodecode.model import repo, repo_group
127 127
128 128 def check_repo(environ, match_dict):
129 129 """
130 130 check for valid repository for proper 404 handling
131 131
132 132 :param environ:
133 133 :param match_dict:
134 134 """
135 135 repo_name = match_dict.get('repo_name')
136 136
137 137 if match_dict.get('f_path'):
138 138 # fix for multiple initial slashes that causes errors
139 139 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
140 140 repo_model = repo.RepoModel()
141 141 by_name_match = repo_model.get_by_repo_name(repo_name)
142 142 # if we match quickly from database, short circuit the operation,
143 143 # and validate repo based on the type.
144 144 if by_name_match:
145 145 return True
146 146
147 147 by_id_match = repo_model.get_repo_by_id(repo_name)
148 148 if by_id_match:
149 149 repo_name = by_id_match.repo_name
150 150 match_dict['repo_name'] = repo_name
151 151 return True
152 152
153 153 return False
154 154
155 155 def check_group(environ, match_dict):
156 156 """
157 157 check for valid repository group path for proper 404 handling
158 158
159 159 :param environ:
160 160 :param match_dict:
161 161 """
162 162 repo_group_name = match_dict.get('group_name')
163 163 repo_group_model = repo_group.RepoGroupModel()
164 164 by_name_match = repo_group_model.get_by_group_name(repo_group_name)
165 165 if by_name_match:
166 166 return True
167 167
168 168 return False
169 169
170 170 def check_user_group(environ, match_dict):
171 171 """
172 172 check for valid user group for proper 404 handling
173 173
174 174 :param environ:
175 175 :param match_dict:
176 176 """
177 177 return True
178 178
179 179 def check_int(environ, match_dict):
180 180 return match_dict.get('id').isdigit()
181 181
182 182
183 183 #==========================================================================
184 184 # CUSTOM ROUTES HERE
185 185 #==========================================================================
186 186
187 187 # MAIN PAGE
188 188 rmap.connect('home', '/', controller='home', action='index')
189 189
190 190 # ping and pylons error test
191 191 rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping')
192 192 rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test')
193 193
194 194 # ADMIN REPOSITORY ROUTES
195 195 with rmap.submapper(path_prefix=ADMIN_PREFIX,
196 196 controller='admin/repos') as m:
197 197 m.connect('repos', '/repos',
198 198 action='create', conditions={'method': ['POST']})
199 199 m.connect('repos', '/repos',
200 200 action='index', conditions={'method': ['GET']})
201 201 m.connect('new_repo', '/create_repository', jsroute=True,
202 202 action='create_repository', conditions={'method': ['GET']})
203 203 m.connect('delete_repo', '/repos/{repo_name}',
204 204 action='delete', conditions={'method': ['DELETE']},
205 205 requirements=URL_NAME_REQUIREMENTS)
206 206 m.connect('repo', '/repos/{repo_name}',
207 207 action='show', conditions={'method': ['GET'],
208 208 'function': check_repo},
209 209 requirements=URL_NAME_REQUIREMENTS)
210 210
211 211 # ADMIN REPOSITORY GROUPS ROUTES
212 212 with rmap.submapper(path_prefix=ADMIN_PREFIX,
213 213 controller='admin/repo_groups') as m:
214 214 m.connect('repo_groups', '/repo_groups',
215 215 action='create', conditions={'method': ['POST']})
216 216 m.connect('repo_groups', '/repo_groups',
217 217 action='index', conditions={'method': ['GET']})
218 218 m.connect('new_repo_group', '/repo_groups/new',
219 219 action='new', conditions={'method': ['GET']})
220 220 m.connect('update_repo_group', '/repo_groups/{group_name}',
221 221 action='update', conditions={'method': ['PUT'],
222 222 'function': check_group},
223 223 requirements=URL_NAME_REQUIREMENTS)
224 224
225 225 # EXTRAS REPO GROUP ROUTES
226 226 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
227 227 action='edit',
228 228 conditions={'method': ['GET'], 'function': check_group},
229 229 requirements=URL_NAME_REQUIREMENTS)
230 230 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
231 231 action='edit',
232 232 conditions={'method': ['PUT'], 'function': check_group},
233 233 requirements=URL_NAME_REQUIREMENTS)
234 234
235 235 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
236 236 action='edit_repo_group_advanced',
237 237 conditions={'method': ['GET'], 'function': check_group},
238 238 requirements=URL_NAME_REQUIREMENTS)
239 239 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
240 240 action='edit_repo_group_advanced',
241 241 conditions={'method': ['PUT'], 'function': check_group},
242 242 requirements=URL_NAME_REQUIREMENTS)
243 243
244 244 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
245 245 action='edit_repo_group_perms',
246 246 conditions={'method': ['GET'], 'function': check_group},
247 247 requirements=URL_NAME_REQUIREMENTS)
248 248 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
249 249 action='update_perms',
250 250 conditions={'method': ['PUT'], 'function': check_group},
251 251 requirements=URL_NAME_REQUIREMENTS)
252 252
253 253 m.connect('delete_repo_group', '/repo_groups/{group_name}',
254 254 action='delete', conditions={'method': ['DELETE'],
255 255 'function': check_group},
256 256 requirements=URL_NAME_REQUIREMENTS)
257 257
258 258 # ADMIN USER ROUTES
259 259 with rmap.submapper(path_prefix=ADMIN_PREFIX,
260 260 controller='admin/users') as m:
261 261 m.connect('users', '/users',
262 262 action='create', conditions={'method': ['POST']})
263 263 m.connect('new_user', '/users/new',
264 264 action='new', conditions={'method': ['GET']})
265 265 m.connect('update_user', '/users/{user_id}',
266 266 action='update', conditions={'method': ['PUT']})
267 267 m.connect('delete_user', '/users/{user_id}',
268 268 action='delete', conditions={'method': ['DELETE']})
269 269 m.connect('edit_user', '/users/{user_id}/edit',
270 270 action='edit', conditions={'method': ['GET']}, jsroute=True)
271 271 m.connect('user', '/users/{user_id}',
272 272 action='show', conditions={'method': ['GET']})
273 273 m.connect('force_password_reset_user', '/users/{user_id}/password_reset',
274 274 action='reset_password', conditions={'method': ['POST']})
275 275 m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group',
276 276 action='create_personal_repo_group', conditions={'method': ['POST']})
277 277
278 278 # EXTRAS USER ROUTES
279 279 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
280 280 action='edit_advanced', conditions={'method': ['GET']})
281 281 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
282 282 action='update_advanced', conditions={'method': ['PUT']})
283 283
284 284 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
285 285 action='edit_global_perms', conditions={'method': ['GET']})
286 286 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
287 287 action='update_global_perms', conditions={'method': ['PUT']})
288 288
289 289 m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary',
290 290 action='edit_perms_summary', conditions={'method': ['GET']})
291 291
292 292 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
293 293 action='edit_emails', conditions={'method': ['GET']})
294 294 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
295 295 action='add_email', conditions={'method': ['PUT']})
296 296 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
297 297 action='delete_email', conditions={'method': ['DELETE']})
298 298
299 299 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
300 300 action='edit_ips', conditions={'method': ['GET']})
301 301 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
302 302 action='add_ip', conditions={'method': ['PUT']})
303 303 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
304 304 action='delete_ip', conditions={'method': ['DELETE']})
305 305
306 306 # ADMIN USER GROUPS REST ROUTES
307 307 with rmap.submapper(path_prefix=ADMIN_PREFIX,
308 308 controller='admin/user_groups') as m:
309 309 m.connect('users_groups', '/user_groups',
310 310 action='create', conditions={'method': ['POST']})
311 311 m.connect('users_groups', '/user_groups',
312 312 action='index', conditions={'method': ['GET']})
313 313 m.connect('new_users_group', '/user_groups/new',
314 314 action='new', conditions={'method': ['GET']})
315 315 m.connect('update_users_group', '/user_groups/{user_group_id}',
316 316 action='update', conditions={'method': ['PUT']})
317 317 m.connect('delete_users_group', '/user_groups/{user_group_id}',
318 318 action='delete', conditions={'method': ['DELETE']})
319 319 m.connect('edit_users_group', '/user_groups/{user_group_id}/edit',
320 320 action='edit', conditions={'method': ['GET']},
321 321 function=check_user_group)
322 322
323 323 # EXTRAS USER GROUP ROUTES
324 324 m.connect('edit_user_group_global_perms',
325 325 '/user_groups/{user_group_id}/edit/global_permissions',
326 326 action='edit_global_perms', conditions={'method': ['GET']})
327 327 m.connect('edit_user_group_global_perms',
328 328 '/user_groups/{user_group_id}/edit/global_permissions',
329 329 action='update_global_perms', conditions={'method': ['PUT']})
330 330 m.connect('edit_user_group_perms_summary',
331 331 '/user_groups/{user_group_id}/edit/permissions_summary',
332 332 action='edit_perms_summary', conditions={'method': ['GET']})
333 333
334 334 m.connect('edit_user_group_perms',
335 335 '/user_groups/{user_group_id}/edit/permissions',
336 336 action='edit_perms', conditions={'method': ['GET']})
337 337 m.connect('edit_user_group_perms',
338 338 '/user_groups/{user_group_id}/edit/permissions',
339 339 action='update_perms', conditions={'method': ['PUT']})
340 340
341 341 m.connect('edit_user_group_advanced',
342 342 '/user_groups/{user_group_id}/edit/advanced',
343 343 action='edit_advanced', conditions={'method': ['GET']})
344 344
345 345 m.connect('edit_user_group_advanced_sync',
346 346 '/user_groups/{user_group_id}/edit/advanced/sync',
347 347 action='edit_advanced_set_synchronization', conditions={'method': ['POST']})
348 348
349 349 m.connect('edit_user_group_members',
350 350 '/user_groups/{user_group_id}/edit/members', jsroute=True,
351 351 action='user_group_members', conditions={'method': ['GET']})
352 352
353 353 # ADMIN PERMISSIONS ROUTES
354 354 with rmap.submapper(path_prefix=ADMIN_PREFIX,
355 355 controller='admin/permissions') as m:
356 356 m.connect('admin_permissions_application', '/permissions/application',
357 357 action='permission_application_update', conditions={'method': ['POST']})
358 358 m.connect('admin_permissions_application', '/permissions/application',
359 359 action='permission_application', conditions={'method': ['GET']})
360 360
361 361 m.connect('admin_permissions_global', '/permissions/global',
362 362 action='permission_global_update', conditions={'method': ['POST']})
363 363 m.connect('admin_permissions_global', '/permissions/global',
364 364 action='permission_global', conditions={'method': ['GET']})
365 365
366 366 m.connect('admin_permissions_object', '/permissions/object',
367 367 action='permission_objects_update', conditions={'method': ['POST']})
368 368 m.connect('admin_permissions_object', '/permissions/object',
369 369 action='permission_objects', conditions={'method': ['GET']})
370 370
371 371 m.connect('admin_permissions_ips', '/permissions/ips',
372 372 action='permission_ips', conditions={'method': ['POST']})
373 373 m.connect('admin_permissions_ips', '/permissions/ips',
374 374 action='permission_ips', conditions={'method': ['GET']})
375 375
376 376 m.connect('admin_permissions_overview', '/permissions/overview',
377 377 action='permission_perms', conditions={'method': ['GET']})
378 378
379 379 # ADMIN DEFAULTS REST ROUTES
380 380 with rmap.submapper(path_prefix=ADMIN_PREFIX,
381 381 controller='admin/defaults') as m:
382 382 m.connect('admin_defaults_repositories', '/defaults/repositories',
383 383 action='update_repository_defaults', conditions={'method': ['POST']})
384 384 m.connect('admin_defaults_repositories', '/defaults/repositories',
385 385 action='index', conditions={'method': ['GET']})
386 386
387 387 # ADMIN DEBUG STYLE ROUTES
388 388 if str2bool(config.get('debug_style')):
389 389 with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style',
390 390 controller='debug_style') as m:
391 391 m.connect('debug_style_home', '',
392 392 action='index', conditions={'method': ['GET']})
393 393 m.connect('debug_style_template', '/t/{t_path}',
394 394 action='template', conditions={'method': ['GET']})
395 395
396 396 # ADMIN SETTINGS ROUTES
397 397 with rmap.submapper(path_prefix=ADMIN_PREFIX,
398 398 controller='admin/settings') as m:
399 399
400 400 # default
401 401 m.connect('admin_settings', '/settings',
402 402 action='settings_global_update',
403 403 conditions={'method': ['POST']})
404 404 m.connect('admin_settings', '/settings',
405 405 action='settings_global', conditions={'method': ['GET']})
406 406
407 407 m.connect('admin_settings_vcs', '/settings/vcs',
408 408 action='settings_vcs_update',
409 409 conditions={'method': ['POST']})
410 410 m.connect('admin_settings_vcs', '/settings/vcs',
411 411 action='settings_vcs',
412 412 conditions={'method': ['GET']})
413 413 m.connect('admin_settings_vcs', '/settings/vcs',
414 414 action='delete_svn_pattern',
415 415 conditions={'method': ['DELETE']})
416 416
417 417 m.connect('admin_settings_mapping', '/settings/mapping',
418 418 action='settings_mapping_update',
419 419 conditions={'method': ['POST']})
420 420 m.connect('admin_settings_mapping', '/settings/mapping',
421 421 action='settings_mapping', conditions={'method': ['GET']})
422 422
423 423 m.connect('admin_settings_global', '/settings/global',
424 424 action='settings_global_update',
425 425 conditions={'method': ['POST']})
426 426 m.connect('admin_settings_global', '/settings/global',
427 427 action='settings_global', conditions={'method': ['GET']})
428 428
429 429 m.connect('admin_settings_visual', '/settings/visual',
430 430 action='settings_visual_update',
431 431 conditions={'method': ['POST']})
432 432 m.connect('admin_settings_visual', '/settings/visual',
433 433 action='settings_visual', conditions={'method': ['GET']})
434 434
435 435 m.connect('admin_settings_issuetracker',
436 436 '/settings/issue-tracker', action='settings_issuetracker',
437 437 conditions={'method': ['GET']})
438 438 m.connect('admin_settings_issuetracker_save',
439 439 '/settings/issue-tracker/save',
440 440 action='settings_issuetracker_save',
441 441 conditions={'method': ['POST']})
442 442 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
443 443 action='settings_issuetracker_test',
444 444 conditions={'method': ['POST']})
445 445 m.connect('admin_issuetracker_delete',
446 446 '/settings/issue-tracker/delete',
447 447 action='settings_issuetracker_delete',
448 448 conditions={'method': ['DELETE']})
449 449
450 450 m.connect('admin_settings_email', '/settings/email',
451 451 action='settings_email_update',
452 452 conditions={'method': ['POST']})
453 453 m.connect('admin_settings_email', '/settings/email',
454 454 action='settings_email', conditions={'method': ['GET']})
455 455
456 456 m.connect('admin_settings_hooks', '/settings/hooks',
457 457 action='settings_hooks_update',
458 458 conditions={'method': ['POST', 'DELETE']})
459 459 m.connect('admin_settings_hooks', '/settings/hooks',
460 460 action='settings_hooks', conditions={'method': ['GET']})
461 461
462 462 m.connect('admin_settings_search', '/settings/search',
463 463 action='settings_search', conditions={'method': ['GET']})
464 464
465 465 m.connect('admin_settings_supervisor', '/settings/supervisor',
466 466 action='settings_supervisor', conditions={'method': ['GET']})
467 467 m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log',
468 468 action='settings_supervisor_log', conditions={'method': ['GET']})
469 469
470 470 m.connect('admin_settings_labs', '/settings/labs',
471 471 action='settings_labs_update',
472 472 conditions={'method': ['POST']})
473 473 m.connect('admin_settings_labs', '/settings/labs',
474 474 action='settings_labs', conditions={'method': ['GET']})
475 475
476 476 # ADMIN MY ACCOUNT
477 477 with rmap.submapper(path_prefix=ADMIN_PREFIX,
478 478 controller='admin/my_account') as m:
479 479
480 480 m.connect('my_account_edit', '/my_account/edit',
481 481 action='my_account_edit', conditions={'method': ['GET']})
482 482 m.connect('my_account', '/my_account/update',
483 483 action='my_account_update', conditions={'method': ['POST']})
484 484
485 485 # NOTE(marcink): this needs to be kept for password force flag to be
486 486 # handler, remove after migration to pyramid
487 487 m.connect('my_account_password', '/my_account/password',
488 488 action='my_account_password', conditions={'method': ['GET']})
489 489
490 490 m.connect('my_account_repos', '/my_account/repos',
491 491 action='my_account_repos', conditions={'method': ['GET']})
492 492
493 493 m.connect('my_account_watched', '/my_account/watched',
494 494 action='my_account_watched', conditions={'method': ['GET']})
495 495
496 496 m.connect('my_account_pullrequests', '/my_account/pull_requests',
497 497 action='my_account_pullrequests', conditions={'method': ['GET']})
498 498
499 499 m.connect('my_account_perms', '/my_account/perms',
500 500 action='my_account_perms', conditions={'method': ['GET']})
501 501
502 502 m.connect('my_account_emails', '/my_account/emails',
503 503 action='my_account_emails', conditions={'method': ['GET']})
504 504 m.connect('my_account_emails', '/my_account/emails',
505 505 action='my_account_emails_add', conditions={'method': ['POST']})
506 506 m.connect('my_account_emails', '/my_account/emails',
507 507 action='my_account_emails_delete', conditions={'method': ['DELETE']})
508 508
509 509 m.connect('my_account_notifications', '/my_account/notifications',
510 510 action='my_notifications',
511 511 conditions={'method': ['GET']})
512 512 m.connect('my_account_notifications_toggle_visibility',
513 513 '/my_account/toggle_visibility',
514 514 action='my_notifications_toggle_visibility',
515 515 conditions={'method': ['POST']})
516 516
517 517 # NOTIFICATION REST ROUTES
518 518 with rmap.submapper(path_prefix=ADMIN_PREFIX,
519 519 controller='admin/notifications') as m:
520 520 m.connect('notifications', '/notifications',
521 521 action='index', conditions={'method': ['GET']})
522 522 m.connect('notifications_mark_all_read', '/notifications/mark_all_read',
523 523 action='mark_all_read', conditions={'method': ['POST']})
524 524 m.connect('/notifications/{notification_id}',
525 525 action='update', conditions={'method': ['PUT']})
526 526 m.connect('/notifications/{notification_id}',
527 527 action='delete', conditions={'method': ['DELETE']})
528 528 m.connect('notification', '/notifications/{notification_id}',
529 529 action='show', conditions={'method': ['GET']})
530 530
531 531 # ADMIN GIST
532 532 with rmap.submapper(path_prefix=ADMIN_PREFIX,
533 533 controller='admin/gists') as m:
534 534 m.connect('gists', '/gists',
535 535 action='create', conditions={'method': ['POST']})
536 536 m.connect('gists', '/gists', jsroute=True,
537 537 action='index', conditions={'method': ['GET']})
538 538 m.connect('new_gist', '/gists/new', jsroute=True,
539 539 action='new', conditions={'method': ['GET']})
540 540
541 541 m.connect('/gists/{gist_id}',
542 542 action='delete', conditions={'method': ['DELETE']})
543 543 m.connect('edit_gist', '/gists/{gist_id}/edit',
544 544 action='edit_form', conditions={'method': ['GET']})
545 545 m.connect('edit_gist', '/gists/{gist_id}/edit',
546 546 action='edit', conditions={'method': ['POST']})
547 547 m.connect(
548 548 'edit_gist_check_revision', '/gists/{gist_id}/edit/check_revision',
549 549 action='check_revision', conditions={'method': ['GET']})
550 550
551 551 m.connect('gist', '/gists/{gist_id}',
552 552 action='show', conditions={'method': ['GET']})
553 553 m.connect('gist_rev', '/gists/{gist_id}/{revision}',
554 554 revision='tip',
555 555 action='show', conditions={'method': ['GET']})
556 556 m.connect('formatted_gist', '/gists/{gist_id}/{revision}/{format}',
557 557 revision='tip',
558 558 action='show', conditions={'method': ['GET']})
559 559 m.connect('formatted_gist_file', '/gists/{gist_id}/{revision}/{format}/{f_path}',
560 560 revision='tip',
561 561 action='show', conditions={'method': ['GET']},
562 562 requirements=URL_NAME_REQUIREMENTS)
563 563
564 564 # USER JOURNAL
565 565 rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,),
566 566 controller='journal', action='index')
567 567 rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,),
568 568 controller='journal', action='journal_rss')
569 569 rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,),
570 570 controller='journal', action='journal_atom')
571 571
572 572 rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,),
573 573 controller='journal', action='public_journal')
574 574
575 575 rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,),
576 576 controller='journal', action='public_journal_rss')
577 577
578 578 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,),
579 579 controller='journal', action='public_journal_rss')
580 580
581 581 rmap.connect('public_journal_atom',
582 582 '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal',
583 583 action='public_journal_atom')
584 584
585 585 rmap.connect('public_journal_atom_old',
586 586 '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal',
587 587 action='public_journal_atom')
588 588
589 589 rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,),
590 590 controller='journal', action='toggle_following', jsroute=True,
591 591 conditions={'method': ['POST']})
592 592
593 593 # FEEDS
594 594 rmap.connect('rss_feed_home', '/{repo_name}/feed/rss',
595 595 controller='feed', action='rss',
596 596 conditions={'function': check_repo},
597 597 requirements=URL_NAME_REQUIREMENTS)
598 598
599 599 rmap.connect('atom_feed_home', '/{repo_name}/feed/atom',
600 600 controller='feed', action='atom',
601 601 conditions={'function': check_repo},
602 602 requirements=URL_NAME_REQUIREMENTS)
603 603
604 604 #==========================================================================
605 605 # REPOSITORY ROUTES
606 606 #==========================================================================
607 607
608 608 rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
609 609 controller='admin/repos', action='repo_creating',
610 610 requirements=URL_NAME_REQUIREMENTS)
611 611 rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
612 612 controller='admin/repos', action='repo_check',
613 613 requirements=URL_NAME_REQUIREMENTS)
614 614
615 615 rmap.connect('repo_stats', '/{repo_name}/repo_stats/{commit_id}',
616 616 controller='summary', action='repo_stats',
617 617 conditions={'function': check_repo},
618 618 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
619 619
620 620 rmap.connect('repo_refs_data', '/{repo_name}/refs-data',
621 621 controller='summary', action='repo_refs_data',
622 622 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
623 623 rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog',
624 624 controller='summary', action='repo_refs_changelog_data',
625 625 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
626 rmap.connect('repo_default_reviewers_data', '/{repo_name}/default-reviewers',
627 controller='summary', action='repo_default_reviewers_data',
628 jsroute=True, requirements=URL_NAME_REQUIREMENTS)
629 626
630 627 rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
631 628 controller='changeset', revision='tip',
632 629 conditions={'function': check_repo},
633 630 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
634 631 rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
635 632 controller='changeset', revision='tip', action='changeset_children',
636 633 conditions={'function': check_repo},
637 634 requirements=URL_NAME_REQUIREMENTS)
638 635 rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
639 636 controller='changeset', revision='tip', action='changeset_parents',
640 637 conditions={'function': check_repo},
641 638 requirements=URL_NAME_REQUIREMENTS)
642 639
643 640 # repo edit options
644 641 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
645 642 controller='admin/repos', action='edit_fields',
646 643 conditions={'method': ['GET'], 'function': check_repo},
647 644 requirements=URL_NAME_REQUIREMENTS)
648 645 rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new',
649 646 controller='admin/repos', action='create_repo_field',
650 647 conditions={'method': ['PUT'], 'function': check_repo},
651 648 requirements=URL_NAME_REQUIREMENTS)
652 649 rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}',
653 650 controller='admin/repos', action='delete_repo_field',
654 651 conditions={'method': ['DELETE'], 'function': check_repo},
655 652 requirements=URL_NAME_REQUIREMENTS)
656 653
657 654 rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle',
658 655 controller='admin/repos', action='toggle_locking',
659 656 conditions={'method': ['GET'], 'function': check_repo},
660 657 requirements=URL_NAME_REQUIREMENTS)
661 658
662 659 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
663 660 controller='admin/repos', action='edit_remote_form',
664 661 conditions={'method': ['GET'], 'function': check_repo},
665 662 requirements=URL_NAME_REQUIREMENTS)
666 663 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
667 664 controller='admin/repos', action='edit_remote',
668 665 conditions={'method': ['PUT'], 'function': check_repo},
669 666 requirements=URL_NAME_REQUIREMENTS)
670 667
671 668 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
672 669 controller='admin/repos', action='edit_statistics_form',
673 670 conditions={'method': ['GET'], 'function': check_repo},
674 671 requirements=URL_NAME_REQUIREMENTS)
675 672 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
676 673 controller='admin/repos', action='edit_statistics',
677 674 conditions={'method': ['PUT'], 'function': check_repo},
678 675 requirements=URL_NAME_REQUIREMENTS)
679 676 rmap.connect('repo_settings_issuetracker',
680 677 '/{repo_name}/settings/issue-tracker',
681 678 controller='admin/repos', action='repo_issuetracker',
682 679 conditions={'method': ['GET'], 'function': check_repo},
683 680 requirements=URL_NAME_REQUIREMENTS)
684 681 rmap.connect('repo_issuetracker_test',
685 682 '/{repo_name}/settings/issue-tracker/test',
686 683 controller='admin/repos', action='repo_issuetracker_test',
687 684 conditions={'method': ['POST'], 'function': check_repo},
688 685 requirements=URL_NAME_REQUIREMENTS)
689 686 rmap.connect('repo_issuetracker_delete',
690 687 '/{repo_name}/settings/issue-tracker/delete',
691 688 controller='admin/repos', action='repo_issuetracker_delete',
692 689 conditions={'method': ['DELETE'], 'function': check_repo},
693 690 requirements=URL_NAME_REQUIREMENTS)
694 691 rmap.connect('repo_issuetracker_save',
695 692 '/{repo_name}/settings/issue-tracker/save',
696 693 controller='admin/repos', action='repo_issuetracker_save',
697 694 conditions={'method': ['POST'], 'function': check_repo},
698 695 requirements=URL_NAME_REQUIREMENTS)
699 696 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
700 697 controller='admin/repos', action='repo_settings_vcs_update',
701 698 conditions={'method': ['POST'], 'function': check_repo},
702 699 requirements=URL_NAME_REQUIREMENTS)
703 700 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
704 701 controller='admin/repos', action='repo_settings_vcs',
705 702 conditions={'method': ['GET'], 'function': check_repo},
706 703 requirements=URL_NAME_REQUIREMENTS)
707 704 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
708 705 controller='admin/repos', action='repo_delete_svn_pattern',
709 706 conditions={'method': ['DELETE'], 'function': check_repo},
710 707 requirements=URL_NAME_REQUIREMENTS)
711 708 rmap.connect('repo_pullrequest_settings', '/{repo_name}/settings/pullrequest',
712 709 controller='admin/repos', action='repo_settings_pullrequest',
713 710 conditions={'method': ['GET', 'POST'], 'function': check_repo},
714 711 requirements=URL_NAME_REQUIREMENTS)
715 712
716 713 # still working url for backward compat.
717 714 rmap.connect('raw_changeset_home_depraced',
718 715 '/{repo_name}/raw-changeset/{revision}',
719 716 controller='changeset', action='changeset_raw',
720 717 revision='tip', conditions={'function': check_repo},
721 718 requirements=URL_NAME_REQUIREMENTS)
722 719
723 720 # new URLs
724 721 rmap.connect('changeset_raw_home',
725 722 '/{repo_name}/changeset-diff/{revision}',
726 723 controller='changeset', action='changeset_raw',
727 724 revision='tip', conditions={'function': check_repo},
728 725 requirements=URL_NAME_REQUIREMENTS)
729 726
730 727 rmap.connect('changeset_patch_home',
731 728 '/{repo_name}/changeset-patch/{revision}',
732 729 controller='changeset', action='changeset_patch',
733 730 revision='tip', conditions={'function': check_repo},
734 731 requirements=URL_NAME_REQUIREMENTS)
735 732
736 733 rmap.connect('changeset_download_home',
737 734 '/{repo_name}/changeset-download/{revision}',
738 735 controller='changeset', action='changeset_download',
739 736 revision='tip', conditions={'function': check_repo},
740 737 requirements=URL_NAME_REQUIREMENTS)
741 738
742 739 rmap.connect('changeset_comment',
743 740 '/{repo_name}/changeset/{revision}/comment', jsroute=True,
744 741 controller='changeset', revision='tip', action='comment',
745 742 conditions={'function': check_repo},
746 743 requirements=URL_NAME_REQUIREMENTS)
747 744
748 745 rmap.connect('changeset_comment_preview',
749 746 '/{repo_name}/changeset/comment/preview', jsroute=True,
750 747 controller='changeset', action='preview_comment',
751 748 conditions={'function': check_repo, 'method': ['POST']},
752 749 requirements=URL_NAME_REQUIREMENTS)
753 750
754 751 rmap.connect('changeset_comment_delete',
755 752 '/{repo_name}/changeset/comment/{comment_id}/delete',
756 753 controller='changeset', action='delete_comment',
757 754 conditions={'function': check_repo, 'method': ['DELETE']},
758 755 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
759 756
760 757 rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}',
761 758 controller='changeset', action='changeset_info',
762 759 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
763 760
764 761 rmap.connect('compare_home',
765 762 '/{repo_name}/compare',
766 763 controller='compare', action='index',
767 764 conditions={'function': check_repo},
768 765 requirements=URL_NAME_REQUIREMENTS)
769 766
770 767 rmap.connect('compare_url',
771 768 '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}',
772 769 controller='compare', action='compare',
773 770 conditions={'function': check_repo},
774 771 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
775 772
776 773 rmap.connect('pullrequest_home',
777 774 '/{repo_name}/pull-request/new', controller='pullrequests',
778 775 action='index', conditions={'function': check_repo,
779 776 'method': ['GET']},
780 777 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
781 778
782 779 rmap.connect('pullrequest',
783 780 '/{repo_name}/pull-request/new', controller='pullrequests',
784 781 action='create', conditions={'function': check_repo,
785 782 'method': ['POST']},
786 783 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
787 784
788 785 rmap.connect('pullrequest_repo_refs',
789 786 '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
790 787 controller='pullrequests',
791 788 action='get_repo_refs',
792 789 conditions={'function': check_repo, 'method': ['GET']},
793 790 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
794 791
795 792 rmap.connect('pullrequest_repo_destinations',
796 793 '/{repo_name}/pull-request/repo-destinations',
797 794 controller='pullrequests',
798 795 action='get_repo_destinations',
799 796 conditions={'function': check_repo, 'method': ['GET']},
800 797 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
801 798
802 799 rmap.connect('pullrequest_show',
803 800 '/{repo_name}/pull-request/{pull_request_id}',
804 801 controller='pullrequests',
805 802 action='show', conditions={'function': check_repo,
806 803 'method': ['GET']},
807 804 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
808 805
809 806 rmap.connect('pullrequest_update',
810 807 '/{repo_name}/pull-request/{pull_request_id}',
811 808 controller='pullrequests',
812 809 action='update', conditions={'function': check_repo,
813 810 'method': ['PUT']},
814 811 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
815 812
816 813 rmap.connect('pullrequest_merge',
817 814 '/{repo_name}/pull-request/{pull_request_id}',
818 815 controller='pullrequests',
819 816 action='merge', conditions={'function': check_repo,
820 817 'method': ['POST']},
821 818 requirements=URL_NAME_REQUIREMENTS)
822 819
823 820 rmap.connect('pullrequest_delete',
824 821 '/{repo_name}/pull-request/{pull_request_id}',
825 822 controller='pullrequests',
826 823 action='delete', conditions={'function': check_repo,
827 824 'method': ['DELETE']},
828 825 requirements=URL_NAME_REQUIREMENTS)
829 826
830 827 rmap.connect('pullrequest_comment',
831 828 '/{repo_name}/pull-request-comment/{pull_request_id}',
832 829 controller='pullrequests',
833 830 action='comment', conditions={'function': check_repo,
834 831 'method': ['POST']},
835 832 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
836 833
837 834 rmap.connect('pullrequest_comment_delete',
838 835 '/{repo_name}/pull-request-comment/{comment_id}/delete',
839 836 controller='pullrequests', action='delete_comment',
840 837 conditions={'function': check_repo, 'method': ['DELETE']},
841 838 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
842 839
843 840 rmap.connect('summary_home_explicit', '/{repo_name}/summary',
844 841 controller='summary', conditions={'function': check_repo},
845 842 requirements=URL_NAME_REQUIREMENTS)
846 843
847 844 rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
848 845 controller='changelog', conditions={'function': check_repo},
849 846 requirements=URL_NAME_REQUIREMENTS)
850 847
851 848 rmap.connect('changelog_summary_home', '/{repo_name}/changelog_summary',
852 849 controller='changelog', action='changelog_summary',
853 850 conditions={'function': check_repo},
854 851 requirements=URL_NAME_REQUIREMENTS)
855 852
856 853 rmap.connect('changelog_file_home',
857 854 '/{repo_name}/changelog/{revision}/{f_path}',
858 855 controller='changelog', f_path=None,
859 856 conditions={'function': check_repo},
860 857 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
861 858
862 859 rmap.connect('changelog_elements', '/{repo_name}/changelog_details',
863 860 controller='changelog', action='changelog_elements',
864 861 conditions={'function': check_repo},
865 862 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
866 863
867 864 rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}',
868 865 controller='files', revision='tip', f_path='',
869 866 conditions={'function': check_repo},
870 867 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
871 868
872 869 rmap.connect('files_home_simple_catchrev',
873 870 '/{repo_name}/files/{revision}',
874 871 controller='files', revision='tip', f_path='',
875 872 conditions={'function': check_repo},
876 873 requirements=URL_NAME_REQUIREMENTS)
877 874
878 875 rmap.connect('files_home_simple_catchall',
879 876 '/{repo_name}/files',
880 877 controller='files', revision='tip', f_path='',
881 878 conditions={'function': check_repo},
882 879 requirements=URL_NAME_REQUIREMENTS)
883 880
884 881 rmap.connect('files_history_home',
885 882 '/{repo_name}/history/{revision}/{f_path}',
886 883 controller='files', action='history', revision='tip', f_path='',
887 884 conditions={'function': check_repo},
888 885 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
889 886
890 887 rmap.connect('files_authors_home',
891 888 '/{repo_name}/authors/{revision}/{f_path}',
892 889 controller='files', action='authors', revision='tip', f_path='',
893 890 conditions={'function': check_repo},
894 891 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
895 892
896 893 rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}',
897 894 controller='files', action='diff', f_path='',
898 895 conditions={'function': check_repo},
899 896 requirements=URL_NAME_REQUIREMENTS)
900 897
901 898 rmap.connect('files_diff_2way_home',
902 899 '/{repo_name}/diff-2way/{f_path}',
903 900 controller='files', action='diff_2way', f_path='',
904 901 conditions={'function': check_repo},
905 902 requirements=URL_NAME_REQUIREMENTS)
906 903
907 904 rmap.connect('files_rawfile_home',
908 905 '/{repo_name}/rawfile/{revision}/{f_path}',
909 906 controller='files', action='rawfile', revision='tip',
910 907 f_path='', conditions={'function': check_repo},
911 908 requirements=URL_NAME_REQUIREMENTS)
912 909
913 910 rmap.connect('files_raw_home',
914 911 '/{repo_name}/raw/{revision}/{f_path}',
915 912 controller='files', action='raw', revision='tip', f_path='',
916 913 conditions={'function': check_repo},
917 914 requirements=URL_NAME_REQUIREMENTS)
918 915
919 916 rmap.connect('files_render_home',
920 917 '/{repo_name}/render/{revision}/{f_path}',
921 918 controller='files', action='index', revision='tip', f_path='',
922 919 rendered=True, conditions={'function': check_repo},
923 920 requirements=URL_NAME_REQUIREMENTS)
924 921
925 922 rmap.connect('files_annotate_home',
926 923 '/{repo_name}/annotate/{revision}/{f_path}',
927 924 controller='files', action='index', revision='tip',
928 925 f_path='', annotate=True, conditions={'function': check_repo},
929 926 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
930 927
931 928 rmap.connect('files_annotate_previous',
932 929 '/{repo_name}/annotate-previous/{revision}/{f_path}',
933 930 controller='files', action='annotate_previous', revision='tip',
934 931 f_path='', annotate=True, conditions={'function': check_repo},
935 932 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
936 933
937 934 rmap.connect('files_edit',
938 935 '/{repo_name}/edit/{revision}/{f_path}',
939 936 controller='files', action='edit', revision='tip',
940 937 f_path='',
941 938 conditions={'function': check_repo, 'method': ['POST']},
942 939 requirements=URL_NAME_REQUIREMENTS)
943 940
944 941 rmap.connect('files_edit_home',
945 942 '/{repo_name}/edit/{revision}/{f_path}',
946 943 controller='files', action='edit_home', revision='tip',
947 944 f_path='', conditions={'function': check_repo},
948 945 requirements=URL_NAME_REQUIREMENTS)
949 946
950 947 rmap.connect('files_add',
951 948 '/{repo_name}/add/{revision}/{f_path}',
952 949 controller='files', action='add', revision='tip',
953 950 f_path='',
954 951 conditions={'function': check_repo, 'method': ['POST']},
955 952 requirements=URL_NAME_REQUIREMENTS)
956 953
957 954 rmap.connect('files_add_home',
958 955 '/{repo_name}/add/{revision}/{f_path}',
959 956 controller='files', action='add_home', revision='tip',
960 957 f_path='', conditions={'function': check_repo},
961 958 requirements=URL_NAME_REQUIREMENTS)
962 959
963 960 rmap.connect('files_delete',
964 961 '/{repo_name}/delete/{revision}/{f_path}',
965 962 controller='files', action='delete', revision='tip',
966 963 f_path='',
967 964 conditions={'function': check_repo, 'method': ['POST']},
968 965 requirements=URL_NAME_REQUIREMENTS)
969 966
970 967 rmap.connect('files_delete_home',
971 968 '/{repo_name}/delete/{revision}/{f_path}',
972 969 controller='files', action='delete_home', revision='tip',
973 970 f_path='', conditions={'function': check_repo},
974 971 requirements=URL_NAME_REQUIREMENTS)
975 972
976 973 rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}',
977 974 controller='files', action='archivefile',
978 975 conditions={'function': check_repo},
979 976 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
980 977
981 978 rmap.connect('files_nodelist_home',
982 979 '/{repo_name}/nodelist/{revision}/{f_path}',
983 980 controller='files', action='nodelist',
984 981 conditions={'function': check_repo},
985 982 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
986 983
987 984 rmap.connect('files_nodetree_full',
988 985 '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
989 986 controller='files', action='nodetree_full',
990 987 conditions={'function': check_repo},
991 988 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
992 989
993 990 rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
994 991 controller='forks', action='fork_create',
995 992 conditions={'function': check_repo, 'method': ['POST']},
996 993 requirements=URL_NAME_REQUIREMENTS)
997 994
998 995 rmap.connect('repo_fork_home', '/{repo_name}/fork',
999 996 controller='forks', action='fork',
1000 997 conditions={'function': check_repo},
1001 998 requirements=URL_NAME_REQUIREMENTS)
1002 999
1003 1000 rmap.connect('repo_forks_home', '/{repo_name}/forks',
1004 1001 controller='forks', action='forks',
1005 1002 conditions={'function': check_repo},
1006 1003 requirements=URL_NAME_REQUIREMENTS)
1007 1004
1008 1005 # must be here for proper group/repo catching pattern
1009 1006 _connect_with_slash(
1010 1007 rmap, 'repo_group_home', '/{group_name}',
1011 1008 controller='home', action='index_repo_group',
1012 1009 conditions={'function': check_group},
1013 1010 requirements=URL_NAME_REQUIREMENTS)
1014 1011
1015 1012 # catch all, at the end
1016 1013 _connect_with_slash(
1017 1014 rmap, 'summary_home', '/{repo_name}', jsroute=True,
1018 1015 controller='summary', action='index',
1019 1016 conditions={'function': check_repo},
1020 1017 requirements=URL_NAME_REQUIREMENTS)
1021 1018
1022 1019 return rmap
1023 1020
1024 1021
1025 1022 def _connect_with_slash(mapper, name, path, *args, **kwargs):
1026 1023 """
1027 1024 Connect a route with an optional trailing slash in `path`.
1028 1025 """
1029 1026 mapper.connect(name + '_slash', path + '/', *args, **kwargs)
1030 1027 mapper.connect(name, path, *args, **kwargs)
@@ -1,326 +1,315 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Summary controller for RhodeCode Enterprise
23 23 """
24 24
25 25 import logging
26 26 from string import lower
27 27
28 28 from pylons import tmpl_context as c, request
29 29 from pylons.i18n.translation import _
30 from beaker.cache import cache_region, region_invalidate
30 from beaker.cache import cache_region
31 31
32 32 from rhodecode.config.conf import (LANGUAGES_EXTENSIONS_MAP)
33 33 from rhodecode.controllers import utils
34 34 from rhodecode.controllers.changelog import _load_changelog_summary
35 35 from rhodecode.lib import caches, helpers as h
36 36 from rhodecode.lib.utils import jsonify
37 37 from rhodecode.lib.utils2 import safe_str
38 38 from rhodecode.lib.auth import (
39 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, XHRRequired)
39 LoginRequired, HasRepoPermissionAnyDecorator, XHRRequired)
40 40 from rhodecode.lib.base import BaseRepoController, render
41 41 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
42 42 from rhodecode.lib.ext_json import json
43 43 from rhodecode.lib.vcs.backends.base import EmptyCommit
44 from rhodecode.lib.vcs.exceptions import (
45 CommitError, EmptyRepositoryError, NodeDoesNotExistError)
44 from rhodecode.lib.vcs.exceptions import CommitError, EmptyRepositoryError
46 45 from rhodecode.model.db import Statistics, CacheKey, User
47 46 from rhodecode.model.repo import ReadmeFinder
48 47
49 48
50 49 log = logging.getLogger(__name__)
51 50
52 51
53 52 class SummaryController(BaseRepoController):
54 53
55 54 def __before__(self):
56 55 super(SummaryController, self).__before__()
57 56
58 57 def __get_readme_data(self, db_repo):
59 58 repo_name = db_repo.repo_name
60 59 log.debug('Looking for README file')
61 60 default_renderer = c.visual.default_renderer
62 61
63 62 @cache_region('long_term')
64 63 def _generate_readme(cache_key):
65 64 readme_data = None
66 65 readme_node = None
67 66 readme_filename = None
68 67 commit = self._get_landing_commit_or_none(db_repo)
69 68 if commit:
70 69 log.debug("Searching for a README file.")
71 70 readme_node = ReadmeFinder(default_renderer).search(commit)
72 71 if readme_node:
73 72 relative_url = h.url('files_raw_home',
74 73 repo_name=repo_name,
75 74 revision=commit.raw_id,
76 75 f_path=readme_node.path)
77 76 readme_data = self._render_readme_or_none(
78 77 commit, readme_node, relative_url)
79 78 readme_filename = readme_node.path
80 79 return readme_data, readme_filename
81 80
82 81 invalidator_context = CacheKey.repo_context_cache(
83 82 _generate_readme, repo_name, CacheKey.CACHE_TYPE_README)
84 83
85 84 with invalidator_context as context:
86 85 context.invalidate()
87 86 computed = context.compute()
88 87
89 88 return computed
90 89
91 90 def _get_landing_commit_or_none(self, db_repo):
92 91 log.debug("Getting the landing commit.")
93 92 try:
94 93 commit = db_repo.get_landing_commit()
95 94 if not isinstance(commit, EmptyCommit):
96 95 return commit
97 96 else:
98 97 log.debug("Repository is empty, no README to render.")
99 98 except CommitError:
100 99 log.exception(
101 100 "Problem getting commit when trying to render the README.")
102 101
103 102 def _render_readme_or_none(self, commit, readme_node, relative_url):
104 103 log.debug(
105 104 'Found README file `%s` rendering...', readme_node.path)
106 105 renderer = MarkupRenderer()
107 106 try:
108 107 html_source = renderer.render(
109 108 readme_node.content, filename=readme_node.path)
110 109 if relative_url:
111 110 return relative_links(html_source, relative_url)
112 111 return html_source
113 112 except Exception:
114 113 log.exception(
115 114 "Exception while trying to render the README")
116 115
117 116 @LoginRequired()
118 117 @HasRepoPermissionAnyDecorator(
119 118 'repository.read', 'repository.write', 'repository.admin')
120 119 def index(self, repo_name):
121 120
122 121 # Prepare the clone URL
123 122
124 123 username = ''
125 124 if c.rhodecode_user.username != User.DEFAULT_USER:
126 125 username = safe_str(c.rhodecode_user.username)
127 126
128 127 _def_clone_uri = _def_clone_uri_by_id = c.clone_uri_tmpl
129 128 if '{repo}' in _def_clone_uri:
130 129 _def_clone_uri_by_id = _def_clone_uri.replace(
131 130 '{repo}', '_{repoid}')
132 131 elif '{repoid}' in _def_clone_uri:
133 132 _def_clone_uri_by_id = _def_clone_uri.replace(
134 133 '_{repoid}', '{repo}')
135 134
136 135 c.clone_repo_url = c.rhodecode_db_repo.clone_url(
137 136 user=username, uri_tmpl=_def_clone_uri)
138 137 c.clone_repo_url_id = c.rhodecode_db_repo.clone_url(
139 138 user=username, uri_tmpl=_def_clone_uri_by_id)
140 139
141 140 # If enabled, get statistics data
142 141
143 142 c.show_stats = bool(c.rhodecode_db_repo.enable_statistics)
144 143
145 144 stats = self.sa.query(Statistics)\
146 145 .filter(Statistics.repository == c.rhodecode_db_repo)\
147 146 .scalar()
148 147
149 148 c.stats_percentage = 0
150 149
151 150 if stats and stats.languages:
152 151 c.no_data = False is c.rhodecode_db_repo.enable_statistics
153 152 lang_stats_d = json.loads(stats.languages)
154 153
155 154 # Sort first by decreasing count and second by the file extension,
156 155 # so we have a consistent output.
157 156 lang_stats_items = sorted(lang_stats_d.iteritems(),
158 157 key=lambda k: (-k[1], k[0]))[:10]
159 158 lang_stats = [(x, {"count": y,
160 159 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
161 160 for x, y in lang_stats_items]
162 161
163 162 c.trending_languages = json.dumps(lang_stats)
164 163 else:
165 164 c.no_data = True
166 165 c.trending_languages = json.dumps({})
167 166
168 167 c.enable_downloads = c.rhodecode_db_repo.enable_downloads
169 168 c.repository_followers = self.scm_model.get_followers(
170 169 c.rhodecode_db_repo)
171 170 c.repository_forks = self.scm_model.get_forks(c.rhodecode_db_repo)
172 171 c.repository_is_user_following = self.scm_model.is_following_repo(
173 172 c.repo_name, c.rhodecode_user.user_id)
174 173
175 174 if c.repository_requirements_missing:
176 175 return render('summary/missing_requirements.mako')
177 176
178 177 c.readme_data, c.readme_file = \
179 178 self.__get_readme_data(c.rhodecode_db_repo)
180 179
181 180 _load_changelog_summary()
182 181
183 182 if request.is_xhr:
184 183 return render('changelog/changelog_summary_data.mako')
185 184
186 185 return render('summary/summary.mako')
187 186
188 187 @LoginRequired()
189 188 @XHRRequired()
190 189 @HasRepoPermissionAnyDecorator(
191 190 'repository.read', 'repository.write', 'repository.admin')
192 191 @jsonify
193 192 def repo_stats(self, repo_name, commit_id):
194 193 _namespace = caches.get_repo_namespace_key(
195 194 caches.SUMMARY_STATS, repo_name)
196 195 show_stats = bool(c.rhodecode_db_repo.enable_statistics)
197 196 cache_manager = caches.get_cache_manager('repo_cache_long', _namespace)
198 197 _cache_key = caches.compute_key_from_params(
199 198 repo_name, commit_id, show_stats)
200 199
201 200 def compute_stats():
202 201 code_stats = {}
203 202 size = 0
204 203 try:
205 204 scm_instance = c.rhodecode_db_repo.scm_instance()
206 205 commit = scm_instance.get_commit(commit_id)
207 206
208 207 for node in commit.get_filenodes_generator():
209 208 size += node.size
210 209 if not show_stats:
211 210 continue
212 211 ext = lower(node.extension)
213 212 ext_info = LANGUAGES_EXTENSIONS_MAP.get(ext)
214 213 if ext_info:
215 214 if ext in code_stats:
216 215 code_stats[ext]['count'] += 1
217 216 else:
218 217 code_stats[ext] = {"count": 1, "desc": ext_info}
219 218 except EmptyRepositoryError:
220 219 pass
221 220 return {'size': h.format_byte_size_binary(size),
222 221 'code_stats': code_stats}
223 222
224 223 stats = cache_manager.get(_cache_key, createfunc=compute_stats)
225 224 return stats
226 225
227 226 def _switcher_reference_data(self, repo_name, references, is_svn):
228 227 """Prepare reference data for given `references`"""
229 228 items = []
230 229 for name, commit_id in references.items():
231 230 use_commit_id = '/' in name or is_svn
232 231 items.append({
233 232 'name': name,
234 233 'commit_id': commit_id,
235 234 'files_url': h.url(
236 235 'files_home',
237 236 repo_name=repo_name,
238 237 f_path=name if is_svn else '',
239 238 revision=commit_id if use_commit_id else name,
240 239 at=name)
241 240 })
242 241 return items
243 242
244 243 @LoginRequired()
245 244 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
246 245 'repository.admin')
247 246 @jsonify
248 247 def repo_refs_data(self, repo_name):
249 248 repo = c.rhodecode_repo
250 249 refs_to_create = [
251 250 (_("Branch"), repo.branches, 'branch'),
252 251 (_("Tag"), repo.tags, 'tag'),
253 252 (_("Bookmark"), repo.bookmarks, 'book'),
254 253 ]
255 254 res = self._create_reference_data(repo, repo_name, refs_to_create)
256 255 data = {
257 256 'more': False,
258 257 'results': res
259 258 }
260 259 return data
261 260
262 @LoginRequired()
263 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
264 'repository.admin')
265 @jsonify
266 def repo_default_reviewers_data(self, repo_name):
267 return {
268 'reviewers': [utils.reviewer_as_json(
269 user=c.rhodecode_db_repo.user, reasons=None)]
270 }
271
272 261 @jsonify
273 262 def repo_refs_changelog_data(self, repo_name):
274 263 repo = c.rhodecode_repo
275 264
276 265 refs_to_create = [
277 266 (_("Branches"), repo.branches, 'branch'),
278 267 (_("Closed branches"), repo.branches_closed, 'branch_closed'),
279 268 # TODO: enable when vcs can handle bookmarks filters
280 269 # (_("Bookmarks"), repo.bookmarks, "book"),
281 270 ]
282 271 res = self._create_reference_data(repo, repo_name, refs_to_create)
283 272 data = {
284 273 'more': False,
285 274 'results': res
286 275 }
287 276 return data
288 277
289 278 def _create_reference_data(self, repo, full_repo_name, refs_to_create):
290 279 format_ref_id = utils.get_format_ref_id(repo)
291 280
292 281 result = []
293 282 for title, refs, ref_type in refs_to_create:
294 283 if refs:
295 284 result.append({
296 285 'text': title,
297 286 'children': self._create_reference_items(
298 287 repo, full_repo_name, refs, ref_type, format_ref_id),
299 288 })
300 289 return result
301 290
302 291 def _create_reference_items(self, repo, full_repo_name, refs, ref_type,
303 292 format_ref_id):
304 293 result = []
305 294 is_svn = h.is_svn(repo)
306 295 for ref_name, raw_id in refs.iteritems():
307 296 files_url = self._create_files_url(
308 297 repo, full_repo_name, ref_name, raw_id, is_svn)
309 298 result.append({
310 299 'text': ref_name,
311 300 'id': format_ref_id(ref_name, raw_id),
312 301 'raw_id': raw_id,
313 302 'type': ref_type,
314 303 'files_url': files_url,
315 304 })
316 305 return result
317 306
318 307 def _create_files_url(self, repo, full_repo_name, ref_name, raw_id,
319 308 is_svn):
320 309 use_commit_id = '/' in ref_name or is_svn
321 310 return h.url(
322 311 'files_home',
323 312 repo_name=full_repo_name,
324 313 f_path=ref_name if is_svn else '',
325 314 revision=raw_id if use_commit_id else ref_name,
326 315 at=ref_name)
@@ -1,107 +1,109 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Utilities to be shared by multiple controllers.
23 23
24 24 Should only contain utilities to be shared in the controller layer.
25 25 """
26 26
27 27 from rhodecode.lib import helpers as h
28 28 from rhodecode.lib.vcs.exceptions import RepositoryError
29 29
30 30
31 31 def parse_path_ref(ref, default_path=None):
32 32 """
33 33 Parse out a path and reference combination and return both parts of it.
34 34
35 35 This is used to allow support of path based comparisons for Subversion
36 36 as an iterim solution in parameter handling.
37 37 """
38 38 if '@' in ref:
39 39 return ref.rsplit('@', 1)
40 40 else:
41 41 return default_path, ref
42 42
43 43
44 44 def get_format_ref_id(repo):
45 45 """Returns a `repo` specific reference formatter function"""
46 46 if h.is_svn(repo):
47 47 return _format_ref_id_svn
48 48 else:
49 49 return _format_ref_id
50 50
51 51
52 52 def _format_ref_id(name, raw_id):
53 53 """Default formatting of a given reference `name`"""
54 54 return name
55 55
56 56
57 57 def _format_ref_id_svn(name, raw_id):
58 58 """Special way of formatting a reference for Subversion including path"""
59 59 return '%s@%s' % (name, raw_id)
60 60
61 61
62 62 def get_commit_from_ref_name(repo, ref_name, ref_type=None):
63 63 """
64 64 Gets the commit for a `ref_name` taking into account `ref_type`.
65 65 Needed in case a bookmark / tag share the same name.
66 66
67 67 :param repo: the repo instance
68 68 :param ref_name: the name of the ref to get
69 69 :param ref_type: optional, used to disambiguate colliding refs
70 70 """
71 71 repo_scm = repo.scm_instance()
72 72 ref_type_mapping = {
73 73 'book': repo_scm.bookmarks,
74 74 'bookmark': repo_scm.bookmarks,
75 75 'tag': repo_scm.tags,
76 76 'branch': repo_scm.branches,
77 77 }
78 78
79 79 commit_id = ref_name
80 80 if repo_scm.alias != 'svn': # pass svn refs straight to backend until
81 81 # the branch issue with svn is fixed
82 82 if ref_type and ref_type in ref_type_mapping:
83 83 try:
84 84 commit_id = ref_type_mapping[ref_type][ref_name]
85 85 except KeyError:
86 86 raise RepositoryError(
87 87 '%s "%s" does not exist' % (ref_type, ref_name))
88 88
89 89 return repo_scm.get_commit(commit_id)
90 90
91 91
92 def reviewer_as_json(user, reasons):
92 def reviewer_as_json(user, reasons, mandatory):
93 93 """
94 94 Returns json struct of a reviewer for frontend
95 95
96 96 :param user: the reviewer
97 97 :param reasons: list of strings of why they are reviewers
98 :param mandatory: bool, to set user as mandatory
98 99 """
99 100
100 101 return {
101 102 'user_id': user.user_id,
102 103 'reasons': reasons,
104 'mandatory': mandatory,
103 105 'username': user.username,
104 106 'firstname': user.firstname,
105 107 'lastname': user.lastname,
106 108 'gravatar_link': h.gravatar_url(user.email, 14),
107 109 }
@@ -1,135 +1,135 b''
1 1
2 2 /******************************************************************************
3 3 * *
4 4 * DO NOT CHANGE THIS FILE MANUALLY *
5 5 * *
6 6 * *
7 7 * This file is automatically generated when the app starts up with *
8 8 * generate_js_files = true *
9 9 * *
10 10 * To add a route here pass jsroute=True to the route definition in the app *
11 11 * *
12 12 ******************************************************************************/
13 13 function registerRCRoutes() {
14 14 // routes registration
15 15 pyroutes.register('new_repo', '/_admin/create_repository', []);
16 16 pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']);
17 17 pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
18 18 pyroutes.register('gists', '/_admin/gists', []);
19 19 pyroutes.register('new_gist', '/_admin/gists/new', []);
20 20 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
21 21 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
22 22 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
23 23 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
24 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/default-reviewers', ['repo_name']);
25 24 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
26 25 pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
27 26 pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
28 27 pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
29 28 pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']);
30 29 pyroutes.register('compare_url', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
31 30 pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
32 31 pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
33 32 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
34 33 pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']);
35 34 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
36 35 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
37 36 pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
38 37 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
39 38 pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']);
40 39 pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
41 40 pyroutes.register('changelog_elements', '/%(repo_name)s/changelog_details', ['repo_name']);
42 41 pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
43 42 pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
44 43 pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
45 44 pyroutes.register('files_annotate_home', '/%(repo_name)s/annotate/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
46 45 pyroutes.register('files_annotate_previous', '/%(repo_name)s/annotate-previous/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
47 46 pyroutes.register('files_archive_home', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
48 47 pyroutes.register('files_nodelist_home', '/%(repo_name)s/nodelist/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
49 48 pyroutes.register('files_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
50 49 pyroutes.register('summary_home_slash', '/%(repo_name)s/', ['repo_name']);
51 50 pyroutes.register('summary_home', '/%(repo_name)s', ['repo_name']);
52 51 pyroutes.register('favicon', '/favicon.ico', []);
53 52 pyroutes.register('robots', '/robots.txt', []);
54 53 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
55 54 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
56 55 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
57 56 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
58 57 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
59 58 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
60 59 pyroutes.register('repo_group_integrations_home', '%(repo_group_name)s/settings/integrations', ['repo_group_name']);
61 60 pyroutes.register('repo_group_integrations_list', '%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
62 61 pyroutes.register('repo_group_integrations_new', '%(repo_group_name)s/settings/integrations/new', ['repo_group_name']);
63 62 pyroutes.register('repo_group_integrations_create', '%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
64 63 pyroutes.register('repo_group_integrations_edit', '%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
65 64 pyroutes.register('repo_integrations_home', '%(repo_name)s/settings/integrations', ['repo_name']);
66 65 pyroutes.register('repo_integrations_list', '%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
67 66 pyroutes.register('repo_integrations_new', '%(repo_name)s/settings/integrations/new', ['repo_name']);
68 67 pyroutes.register('repo_integrations_create', '%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
69 68 pyroutes.register('repo_integrations_edit', '%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
70 69 pyroutes.register('ops_ping', '_admin/ops/ping', []);
71 70 pyroutes.register('admin_home', '/_admin', []);
72 71 pyroutes.register('admin_audit_logs', '_admin/audit_logs', []);
73 72 pyroutes.register('pull_requests_global_0', '_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
74 73 pyroutes.register('pull_requests_global_1', '_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
75 74 pyroutes.register('pull_requests_global', '_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
76 75 pyroutes.register('admin_settings_open_source', '_admin/settings/open_source', []);
77 76 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '_admin/settings/vcs/svn_generate_cfg', []);
78 77 pyroutes.register('admin_settings_system', '_admin/settings/system', []);
79 78 pyroutes.register('admin_settings_system_update', '_admin/settings/system/updates', []);
80 79 pyroutes.register('admin_settings_sessions', '_admin/settings/sessions', []);
81 80 pyroutes.register('admin_settings_sessions_cleanup', '_admin/settings/sessions/cleanup', []);
82 81 pyroutes.register('users', '_admin/users', []);
83 82 pyroutes.register('users_data', '_admin/users_data', []);
84 83 pyroutes.register('edit_user_auth_tokens', '_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
85 84 pyroutes.register('edit_user_auth_tokens_add', '_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
86 85 pyroutes.register('edit_user_auth_tokens_delete', '_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
87 86 pyroutes.register('edit_user_groups_management', '_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
88 87 pyroutes.register('edit_user_groups_management_updates', '_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
89 88 pyroutes.register('edit_user_audit_logs', '_admin/users/%(user_id)s/edit/audit', ['user_id']);
90 89 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
91 90 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
92 91 pyroutes.register('channelstream_proxy', '/_channelstream', []);
93 92 pyroutes.register('login', '/_admin/login', []);
94 93 pyroutes.register('logout', '/_admin/logout', []);
95 94 pyroutes.register('register', '/_admin/register', []);
96 95 pyroutes.register('reset_password', '/_admin/password_reset', []);
97 96 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
98 97 pyroutes.register('home', '/', []);
99 98 pyroutes.register('user_autocomplete_data', '/_users', []);
100 99 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
101 100 pyroutes.register('repo_list_data', '/_repos', []);
102 101 pyroutes.register('goto_switcher_data', '/_goto_data', []);
103 102 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
104 103 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
105 104 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
106 105 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
107 106 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
108 107 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
109 108 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
110 109 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
111 110 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
112 111 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
113 112 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
114 113 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
115 114 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
116 115 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
117 116 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
118 117 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
118 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
119 119 pyroutes.register('repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
120 120 pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
121 121 pyroutes.register('strip', '/%(repo_name)s/settings/strip', ['repo_name']);
122 122 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
123 123 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
124 124 pyroutes.register('search', '/_admin/search', []);
125 125 pyroutes.register('search_repo', '/%(repo_name)s/search', ['repo_name']);
126 126 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
127 127 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
128 128 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
129 129 pyroutes.register('my_account_password_update', '/_admin/my_account/password', []);
130 130 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
131 131 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
132 132 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
133 133 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
134 134 pyroutes.register('apiv2', '/_admin/api', []);
135 135 }
General Comments 0
You need to be logged in to leave comments. Login now