##// END OF EJS Templates
rss: use permalinks without slashes for feeds. Fixes #5557
marcink -
r3810:d0cfe4e5 stable
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,504 +1,512 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
3 # Copyright (C) 2016-2019 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 from rhodecode.apps._base import add_route_with_slash
20 from rhodecode.apps._base import add_route_with_slash
21
21
22
22
23 def includeme(config):
23 def includeme(config):
24
24
25 # repo creating checks, special cases that aren't repo routes
25 # repo creating checks, special cases that aren't repo routes
26 config.add_route(
26 config.add_route(
27 name='repo_creating',
27 name='repo_creating',
28 pattern='/{repo_name:.*?[^/]}/repo_creating')
28 pattern='/{repo_name:.*?[^/]}/repo_creating')
29
29
30 config.add_route(
30 config.add_route(
31 name='repo_creating_check',
31 name='repo_creating_check',
32 pattern='/{repo_name:.*?[^/]}/repo_creating_check')
32 pattern='/{repo_name:.*?[^/]}/repo_creating_check')
33
33
34 # Summary
34 # Summary
35 # NOTE(marcink): one additional route is defined in very bottom, catch
35 # NOTE(marcink): one additional route is defined in very bottom, catch
36 # all pattern
36 # all pattern
37 config.add_route(
37 config.add_route(
38 name='repo_summary_explicit',
38 name='repo_summary_explicit',
39 pattern='/{repo_name:.*?[^/]}/summary', repo_route=True)
39 pattern='/{repo_name:.*?[^/]}/summary', repo_route=True)
40 config.add_route(
40 config.add_route(
41 name='repo_summary_commits',
41 name='repo_summary_commits',
42 pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
42 pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
43
43
44 # Commits
44 # Commits
45 config.add_route(
45 config.add_route(
46 name='repo_commit',
46 name='repo_commit',
47 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
47 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
48
48
49 config.add_route(
49 config.add_route(
50 name='repo_commit_children',
50 name='repo_commit_children',
51 pattern='/{repo_name:.*?[^/]}/changeset_children/{commit_id}', repo_route=True)
51 pattern='/{repo_name:.*?[^/]}/changeset_children/{commit_id}', repo_route=True)
52
52
53 config.add_route(
53 config.add_route(
54 name='repo_commit_parents',
54 name='repo_commit_parents',
55 pattern='/{repo_name:.*?[^/]}/changeset_parents/{commit_id}', repo_route=True)
55 pattern='/{repo_name:.*?[^/]}/changeset_parents/{commit_id}', repo_route=True)
56
56
57 config.add_route(
57 config.add_route(
58 name='repo_commit_raw',
58 name='repo_commit_raw',
59 pattern='/{repo_name:.*?[^/]}/changeset-diff/{commit_id}', repo_route=True)
59 pattern='/{repo_name:.*?[^/]}/changeset-diff/{commit_id}', repo_route=True)
60
60
61 config.add_route(
61 config.add_route(
62 name='repo_commit_patch',
62 name='repo_commit_patch',
63 pattern='/{repo_name:.*?[^/]}/changeset-patch/{commit_id}', repo_route=True)
63 pattern='/{repo_name:.*?[^/]}/changeset-patch/{commit_id}', repo_route=True)
64
64
65 config.add_route(
65 config.add_route(
66 name='repo_commit_download',
66 name='repo_commit_download',
67 pattern='/{repo_name:.*?[^/]}/changeset-download/{commit_id}', repo_route=True)
67 pattern='/{repo_name:.*?[^/]}/changeset-download/{commit_id}', repo_route=True)
68
68
69 config.add_route(
69 config.add_route(
70 name='repo_commit_data',
70 name='repo_commit_data',
71 pattern='/{repo_name:.*?[^/]}/changeset-data/{commit_id}', repo_route=True)
71 pattern='/{repo_name:.*?[^/]}/changeset-data/{commit_id}', repo_route=True)
72
72
73 config.add_route(
73 config.add_route(
74 name='repo_commit_comment_create',
74 name='repo_commit_comment_create',
75 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/create', repo_route=True)
75 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/create', repo_route=True)
76
76
77 config.add_route(
77 config.add_route(
78 name='repo_commit_comment_preview',
78 name='repo_commit_comment_preview',
79 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/preview', repo_route=True)
79 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/preview', repo_route=True)
80
80
81 config.add_route(
81 config.add_route(
82 name='repo_commit_comment_delete',
82 name='repo_commit_comment_delete',
83 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/{comment_id}/delete', repo_route=True)
83 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/{comment_id}/delete', repo_route=True)
84
84
85 # still working url for backward compat.
85 # still working url for backward compat.
86 config.add_route(
86 config.add_route(
87 name='repo_commit_raw_deprecated',
87 name='repo_commit_raw_deprecated',
88 pattern='/{repo_name:.*?[^/]}/raw-changeset/{commit_id}', repo_route=True)
88 pattern='/{repo_name:.*?[^/]}/raw-changeset/{commit_id}', repo_route=True)
89
89
90 # Files
90 # Files
91 config.add_route(
91 config.add_route(
92 name='repo_archivefile',
92 name='repo_archivefile',
93 pattern='/{repo_name:.*?[^/]}/archive/{fname:.*}', repo_route=True)
93 pattern='/{repo_name:.*?[^/]}/archive/{fname:.*}', repo_route=True)
94
94
95 config.add_route(
95 config.add_route(
96 name='repo_files_diff',
96 name='repo_files_diff',
97 pattern='/{repo_name:.*?[^/]}/diff/{f_path:.*}', repo_route=True)
97 pattern='/{repo_name:.*?[^/]}/diff/{f_path:.*}', repo_route=True)
98 config.add_route( # legacy route to make old links work
98 config.add_route( # legacy route to make old links work
99 name='repo_files_diff_2way_redirect',
99 name='repo_files_diff_2way_redirect',
100 pattern='/{repo_name:.*?[^/]}/diff-2way/{f_path:.*}', repo_route=True)
100 pattern='/{repo_name:.*?[^/]}/diff-2way/{f_path:.*}', repo_route=True)
101
101
102 config.add_route(
102 config.add_route(
103 name='repo_files',
103 name='repo_files',
104 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/{f_path:.*}', repo_route=True)
104 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/{f_path:.*}', repo_route=True)
105 config.add_route(
105 config.add_route(
106 name='repo_files:default_path',
106 name='repo_files:default_path',
107 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/', repo_route=True)
107 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/', repo_route=True)
108 config.add_route(
108 config.add_route(
109 name='repo_files:default_commit',
109 name='repo_files:default_commit',
110 pattern='/{repo_name:.*?[^/]}/files', repo_route=True)
110 pattern='/{repo_name:.*?[^/]}/files', repo_route=True)
111
111
112 config.add_route(
112 config.add_route(
113 name='repo_files:rendered',
113 name='repo_files:rendered',
114 pattern='/{repo_name:.*?[^/]}/render/{commit_id}/{f_path:.*}', repo_route=True)
114 pattern='/{repo_name:.*?[^/]}/render/{commit_id}/{f_path:.*}', repo_route=True)
115
115
116 config.add_route(
116 config.add_route(
117 name='repo_files:annotated',
117 name='repo_files:annotated',
118 pattern='/{repo_name:.*?[^/]}/annotate/{commit_id}/{f_path:.*}', repo_route=True)
118 pattern='/{repo_name:.*?[^/]}/annotate/{commit_id}/{f_path:.*}', repo_route=True)
119 config.add_route(
119 config.add_route(
120 name='repo_files:annotated_previous',
120 name='repo_files:annotated_previous',
121 pattern='/{repo_name:.*?[^/]}/annotate-previous/{commit_id}/{f_path:.*}', repo_route=True)
121 pattern='/{repo_name:.*?[^/]}/annotate-previous/{commit_id}/{f_path:.*}', repo_route=True)
122
122
123 config.add_route(
123 config.add_route(
124 name='repo_nodetree_full',
124 name='repo_nodetree_full',
125 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/{f_path:.*}', repo_route=True)
125 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/{f_path:.*}', repo_route=True)
126 config.add_route(
126 config.add_route(
127 name='repo_nodetree_full:default_path',
127 name='repo_nodetree_full:default_path',
128 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/', repo_route=True)
128 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/', repo_route=True)
129
129
130 config.add_route(
130 config.add_route(
131 name='repo_files_nodelist',
131 name='repo_files_nodelist',
132 pattern='/{repo_name:.*?[^/]}/nodelist/{commit_id}/{f_path:.*}', repo_route=True)
132 pattern='/{repo_name:.*?[^/]}/nodelist/{commit_id}/{f_path:.*}', repo_route=True)
133
133
134 config.add_route(
134 config.add_route(
135 name='repo_file_raw',
135 name='repo_file_raw',
136 pattern='/{repo_name:.*?[^/]}/raw/{commit_id}/{f_path:.*}', repo_route=True)
136 pattern='/{repo_name:.*?[^/]}/raw/{commit_id}/{f_path:.*}', repo_route=True)
137
137
138 config.add_route(
138 config.add_route(
139 name='repo_file_download',
139 name='repo_file_download',
140 pattern='/{repo_name:.*?[^/]}/download/{commit_id}/{f_path:.*}', repo_route=True)
140 pattern='/{repo_name:.*?[^/]}/download/{commit_id}/{f_path:.*}', repo_route=True)
141 config.add_route( # backward compat to keep old links working
141 config.add_route( # backward compat to keep old links working
142 name='repo_file_download:legacy',
142 name='repo_file_download:legacy',
143 pattern='/{repo_name:.*?[^/]}/rawfile/{commit_id}/{f_path:.*}',
143 pattern='/{repo_name:.*?[^/]}/rawfile/{commit_id}/{f_path:.*}',
144 repo_route=True)
144 repo_route=True)
145
145
146 config.add_route(
146 config.add_route(
147 name='repo_file_history',
147 name='repo_file_history',
148 pattern='/{repo_name:.*?[^/]}/history/{commit_id}/{f_path:.*}', repo_route=True)
148 pattern='/{repo_name:.*?[^/]}/history/{commit_id}/{f_path:.*}', repo_route=True)
149
149
150 config.add_route(
150 config.add_route(
151 name='repo_file_authors',
151 name='repo_file_authors',
152 pattern='/{repo_name:.*?[^/]}/authors/{commit_id}/{f_path:.*}', repo_route=True)
152 pattern='/{repo_name:.*?[^/]}/authors/{commit_id}/{f_path:.*}', repo_route=True)
153
153
154 config.add_route(
154 config.add_route(
155 name='repo_files_remove_file',
155 name='repo_files_remove_file',
156 pattern='/{repo_name:.*?[^/]}/remove_file/{commit_id}/{f_path:.*}',
156 pattern='/{repo_name:.*?[^/]}/remove_file/{commit_id}/{f_path:.*}',
157 repo_route=True)
157 repo_route=True)
158 config.add_route(
158 config.add_route(
159 name='repo_files_delete_file',
159 name='repo_files_delete_file',
160 pattern='/{repo_name:.*?[^/]}/delete_file/{commit_id}/{f_path:.*}',
160 pattern='/{repo_name:.*?[^/]}/delete_file/{commit_id}/{f_path:.*}',
161 repo_route=True)
161 repo_route=True)
162 config.add_route(
162 config.add_route(
163 name='repo_files_edit_file',
163 name='repo_files_edit_file',
164 pattern='/{repo_name:.*?[^/]}/edit_file/{commit_id}/{f_path:.*}',
164 pattern='/{repo_name:.*?[^/]}/edit_file/{commit_id}/{f_path:.*}',
165 repo_route=True)
165 repo_route=True)
166 config.add_route(
166 config.add_route(
167 name='repo_files_update_file',
167 name='repo_files_update_file',
168 pattern='/{repo_name:.*?[^/]}/update_file/{commit_id}/{f_path:.*}',
168 pattern='/{repo_name:.*?[^/]}/update_file/{commit_id}/{f_path:.*}',
169 repo_route=True)
169 repo_route=True)
170 config.add_route(
170 config.add_route(
171 name='repo_files_add_file',
171 name='repo_files_add_file',
172 pattern='/{repo_name:.*?[^/]}/add_file/{commit_id}/{f_path:.*}',
172 pattern='/{repo_name:.*?[^/]}/add_file/{commit_id}/{f_path:.*}',
173 repo_route=True)
173 repo_route=True)
174 config.add_route(
174 config.add_route(
175 name='repo_files_upload_file',
175 name='repo_files_upload_file',
176 pattern='/{repo_name:.*?[^/]}/upload_file/{commit_id}/{f_path:.*}',
176 pattern='/{repo_name:.*?[^/]}/upload_file/{commit_id}/{f_path:.*}',
177 repo_route=True)
177 repo_route=True)
178 config.add_route(
178 config.add_route(
179 name='repo_files_create_file',
179 name='repo_files_create_file',
180 pattern='/{repo_name:.*?[^/]}/create_file/{commit_id}/{f_path:.*}',
180 pattern='/{repo_name:.*?[^/]}/create_file/{commit_id}/{f_path:.*}',
181 repo_route=True)
181 repo_route=True)
182
182
183 # Refs data
183 # Refs data
184 config.add_route(
184 config.add_route(
185 name='repo_refs_data',
185 name='repo_refs_data',
186 pattern='/{repo_name:.*?[^/]}/refs-data', repo_route=True)
186 pattern='/{repo_name:.*?[^/]}/refs-data', repo_route=True)
187
187
188 config.add_route(
188 config.add_route(
189 name='repo_refs_changelog_data',
189 name='repo_refs_changelog_data',
190 pattern='/{repo_name:.*?[^/]}/refs-data-changelog', repo_route=True)
190 pattern='/{repo_name:.*?[^/]}/refs-data-changelog', repo_route=True)
191
191
192 config.add_route(
192 config.add_route(
193 name='repo_stats',
193 name='repo_stats',
194 pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True)
194 pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True)
195
195
196 # Commits
196 # Commits
197 config.add_route(
197 config.add_route(
198 name='repo_commits',
198 name='repo_commits',
199 pattern='/{repo_name:.*?[^/]}/commits', repo_route=True)
199 pattern='/{repo_name:.*?[^/]}/commits', repo_route=True)
200 config.add_route(
200 config.add_route(
201 name='repo_commits_file',
201 name='repo_commits_file',
202 pattern='/{repo_name:.*?[^/]}/commits/{commit_id}/{f_path:.*}', repo_route=True)
202 pattern='/{repo_name:.*?[^/]}/commits/{commit_id}/{f_path:.*}', repo_route=True)
203 config.add_route(
203 config.add_route(
204 name='repo_commits_elements',
204 name='repo_commits_elements',
205 pattern='/{repo_name:.*?[^/]}/commits_elements', repo_route=True)
205 pattern='/{repo_name:.*?[^/]}/commits_elements', repo_route=True)
206 config.add_route(
206 config.add_route(
207 name='repo_commits_elements_file',
207 name='repo_commits_elements_file',
208 pattern='/{repo_name:.*?[^/]}/commits_elements/{commit_id}/{f_path:.*}', repo_route=True)
208 pattern='/{repo_name:.*?[^/]}/commits_elements/{commit_id}/{f_path:.*}', repo_route=True)
209
209
210 # Changelog (old deprecated name for commits page)
210 # Changelog (old deprecated name for commits page)
211 config.add_route(
211 config.add_route(
212 name='repo_changelog',
212 name='repo_changelog',
213 pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True)
213 pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True)
214 config.add_route(
214 config.add_route(
215 name='repo_changelog_file',
215 name='repo_changelog_file',
216 pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True)
216 pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True)
217
217
218 # Compare
218 # Compare
219 config.add_route(
219 config.add_route(
220 name='repo_compare_select',
220 name='repo_compare_select',
221 pattern='/{repo_name:.*?[^/]}/compare', repo_route=True)
221 pattern='/{repo_name:.*?[^/]}/compare', repo_route=True)
222
222
223 config.add_route(
223 config.add_route(
224 name='repo_compare',
224 name='repo_compare',
225 pattern='/{repo_name:.*?[^/]}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}', repo_route=True)
225 pattern='/{repo_name:.*?[^/]}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}', repo_route=True)
226
226
227 # Tags
227 # Tags
228 config.add_route(
228 config.add_route(
229 name='tags_home',
229 name='tags_home',
230 pattern='/{repo_name:.*?[^/]}/tags', repo_route=True)
230 pattern='/{repo_name:.*?[^/]}/tags', repo_route=True)
231
231
232 # Branches
232 # Branches
233 config.add_route(
233 config.add_route(
234 name='branches_home',
234 name='branches_home',
235 pattern='/{repo_name:.*?[^/]}/branches', repo_route=True)
235 pattern='/{repo_name:.*?[^/]}/branches', repo_route=True)
236
236
237 # Bookmarks
237 # Bookmarks
238 config.add_route(
238 config.add_route(
239 name='bookmarks_home',
239 name='bookmarks_home',
240 pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True)
240 pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True)
241
241
242 # Forks
242 # Forks
243 config.add_route(
243 config.add_route(
244 name='repo_fork_new',
244 name='repo_fork_new',
245 pattern='/{repo_name:.*?[^/]}/fork', repo_route=True,
245 pattern='/{repo_name:.*?[^/]}/fork', repo_route=True,
246 repo_forbid_when_archived=True,
246 repo_forbid_when_archived=True,
247 repo_accepted_types=['hg', 'git'])
247 repo_accepted_types=['hg', 'git'])
248
248
249 config.add_route(
249 config.add_route(
250 name='repo_fork_create',
250 name='repo_fork_create',
251 pattern='/{repo_name:.*?[^/]}/fork/create', repo_route=True,
251 pattern='/{repo_name:.*?[^/]}/fork/create', repo_route=True,
252 repo_forbid_when_archived=True,
252 repo_forbid_when_archived=True,
253 repo_accepted_types=['hg', 'git'])
253 repo_accepted_types=['hg', 'git'])
254
254
255 config.add_route(
255 config.add_route(
256 name='repo_forks_show_all',
256 name='repo_forks_show_all',
257 pattern='/{repo_name:.*?[^/]}/forks', repo_route=True,
257 pattern='/{repo_name:.*?[^/]}/forks', repo_route=True,
258 repo_accepted_types=['hg', 'git'])
258 repo_accepted_types=['hg', 'git'])
259 config.add_route(
259 config.add_route(
260 name='repo_forks_data',
260 name='repo_forks_data',
261 pattern='/{repo_name:.*?[^/]}/forks/data', repo_route=True,
261 pattern='/{repo_name:.*?[^/]}/forks/data', repo_route=True,
262 repo_accepted_types=['hg', 'git'])
262 repo_accepted_types=['hg', 'git'])
263
263
264 # Pull Requests
264 # Pull Requests
265 config.add_route(
265 config.add_route(
266 name='pullrequest_show',
266 name='pullrequest_show',
267 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}',
267 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}',
268 repo_route=True)
268 repo_route=True)
269
269
270 config.add_route(
270 config.add_route(
271 name='pullrequest_show_all',
271 name='pullrequest_show_all',
272 pattern='/{repo_name:.*?[^/]}/pull-request',
272 pattern='/{repo_name:.*?[^/]}/pull-request',
273 repo_route=True, repo_accepted_types=['hg', 'git'])
273 repo_route=True, repo_accepted_types=['hg', 'git'])
274
274
275 config.add_route(
275 config.add_route(
276 name='pullrequest_show_all_data',
276 name='pullrequest_show_all_data',
277 pattern='/{repo_name:.*?[^/]}/pull-request-data',
277 pattern='/{repo_name:.*?[^/]}/pull-request-data',
278 repo_route=True, repo_accepted_types=['hg', 'git'])
278 repo_route=True, repo_accepted_types=['hg', 'git'])
279
279
280 config.add_route(
280 config.add_route(
281 name='pullrequest_repo_refs',
281 name='pullrequest_repo_refs',
282 pattern='/{repo_name:.*?[^/]}/pull-request/refs/{target_repo_name:.*?[^/]}',
282 pattern='/{repo_name:.*?[^/]}/pull-request/refs/{target_repo_name:.*?[^/]}',
283 repo_route=True)
283 repo_route=True)
284
284
285 config.add_route(
285 config.add_route(
286 name='pullrequest_repo_targets',
286 name='pullrequest_repo_targets',
287 pattern='/{repo_name:.*?[^/]}/pull-request/repo-targets',
287 pattern='/{repo_name:.*?[^/]}/pull-request/repo-targets',
288 repo_route=True)
288 repo_route=True)
289
289
290 config.add_route(
290 config.add_route(
291 name='pullrequest_new',
291 name='pullrequest_new',
292 pattern='/{repo_name:.*?[^/]}/pull-request/new',
292 pattern='/{repo_name:.*?[^/]}/pull-request/new',
293 repo_route=True, repo_accepted_types=['hg', 'git'],
293 repo_route=True, repo_accepted_types=['hg', 'git'],
294 repo_forbid_when_archived=True)
294 repo_forbid_when_archived=True)
295
295
296 config.add_route(
296 config.add_route(
297 name='pullrequest_create',
297 name='pullrequest_create',
298 pattern='/{repo_name:.*?[^/]}/pull-request/create',
298 pattern='/{repo_name:.*?[^/]}/pull-request/create',
299 repo_route=True, repo_accepted_types=['hg', 'git'],
299 repo_route=True, repo_accepted_types=['hg', 'git'],
300 repo_forbid_when_archived=True)
300 repo_forbid_when_archived=True)
301
301
302 config.add_route(
302 config.add_route(
303 name='pullrequest_update',
303 name='pullrequest_update',
304 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/update',
304 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/update',
305 repo_route=True, repo_forbid_when_archived=True)
305 repo_route=True, repo_forbid_when_archived=True)
306
306
307 config.add_route(
307 config.add_route(
308 name='pullrequest_merge',
308 name='pullrequest_merge',
309 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/merge',
309 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/merge',
310 repo_route=True, repo_forbid_when_archived=True)
310 repo_route=True, repo_forbid_when_archived=True)
311
311
312 config.add_route(
312 config.add_route(
313 name='pullrequest_delete',
313 name='pullrequest_delete',
314 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/delete',
314 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/delete',
315 repo_route=True, repo_forbid_when_archived=True)
315 repo_route=True, repo_forbid_when_archived=True)
316
316
317 config.add_route(
317 config.add_route(
318 name='pullrequest_comment_create',
318 name='pullrequest_comment_create',
319 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment',
319 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment',
320 repo_route=True)
320 repo_route=True)
321
321
322 config.add_route(
322 config.add_route(
323 name='pullrequest_comment_delete',
323 name='pullrequest_comment_delete',
324 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete',
324 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete',
325 repo_route=True, repo_accepted_types=['hg', 'git'])
325 repo_route=True, repo_accepted_types=['hg', 'git'])
326
326
327 # Artifacts, (EE feature)
327 # Artifacts, (EE feature)
328 config.add_route(
328 config.add_route(
329 name='repo_artifacts_list',
329 name='repo_artifacts_list',
330 pattern='/{repo_name:.*?[^/]}/artifacts', repo_route=True)
330 pattern='/{repo_name:.*?[^/]}/artifacts', repo_route=True)
331
331
332 # Settings
332 # Settings
333 config.add_route(
333 config.add_route(
334 name='edit_repo',
334 name='edit_repo',
335 pattern='/{repo_name:.*?[^/]}/settings', repo_route=True)
335 pattern='/{repo_name:.*?[^/]}/settings', repo_route=True)
336 # update is POST on edit_repo
336 # update is POST on edit_repo
337
337
338 # Settings advanced
338 # Settings advanced
339 config.add_route(
339 config.add_route(
340 name='edit_repo_advanced',
340 name='edit_repo_advanced',
341 pattern='/{repo_name:.*?[^/]}/settings/advanced', repo_route=True)
341 pattern='/{repo_name:.*?[^/]}/settings/advanced', repo_route=True)
342 config.add_route(
342 config.add_route(
343 name='edit_repo_advanced_archive',
343 name='edit_repo_advanced_archive',
344 pattern='/{repo_name:.*?[^/]}/settings/advanced/archive', repo_route=True)
344 pattern='/{repo_name:.*?[^/]}/settings/advanced/archive', repo_route=True)
345 config.add_route(
345 config.add_route(
346 name='edit_repo_advanced_delete',
346 name='edit_repo_advanced_delete',
347 pattern='/{repo_name:.*?[^/]}/settings/advanced/delete', repo_route=True)
347 pattern='/{repo_name:.*?[^/]}/settings/advanced/delete', repo_route=True)
348 config.add_route(
348 config.add_route(
349 name='edit_repo_advanced_locking',
349 name='edit_repo_advanced_locking',
350 pattern='/{repo_name:.*?[^/]}/settings/advanced/locking', repo_route=True)
350 pattern='/{repo_name:.*?[^/]}/settings/advanced/locking', repo_route=True)
351 config.add_route(
351 config.add_route(
352 name='edit_repo_advanced_journal',
352 name='edit_repo_advanced_journal',
353 pattern='/{repo_name:.*?[^/]}/settings/advanced/journal', repo_route=True)
353 pattern='/{repo_name:.*?[^/]}/settings/advanced/journal', repo_route=True)
354 config.add_route(
354 config.add_route(
355 name='edit_repo_advanced_fork',
355 name='edit_repo_advanced_fork',
356 pattern='/{repo_name:.*?[^/]}/settings/advanced/fork', repo_route=True)
356 pattern='/{repo_name:.*?[^/]}/settings/advanced/fork', repo_route=True)
357
357
358 config.add_route(
358 config.add_route(
359 name='edit_repo_advanced_hooks',
359 name='edit_repo_advanced_hooks',
360 pattern='/{repo_name:.*?[^/]}/settings/advanced/hooks', repo_route=True)
360 pattern='/{repo_name:.*?[^/]}/settings/advanced/hooks', repo_route=True)
361
361
362 # Caches
362 # Caches
363 config.add_route(
363 config.add_route(
364 name='edit_repo_caches',
364 name='edit_repo_caches',
365 pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True)
365 pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True)
366
366
367 # Permissions
367 # Permissions
368 config.add_route(
368 config.add_route(
369 name='edit_repo_perms',
369 name='edit_repo_perms',
370 pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True)
370 pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True)
371
371
372 config.add_route(
372 config.add_route(
373 name='edit_repo_perms_set_private',
373 name='edit_repo_perms_set_private',
374 pattern='/{repo_name:.*?[^/]}/settings/permissions/set_private', repo_route=True)
374 pattern='/{repo_name:.*?[^/]}/settings/permissions/set_private', repo_route=True)
375
375
376 # Permissions Branch (EE feature)
376 # Permissions Branch (EE feature)
377 config.add_route(
377 config.add_route(
378 name='edit_repo_perms_branch',
378 name='edit_repo_perms_branch',
379 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions', repo_route=True)
379 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions', repo_route=True)
380 config.add_route(
380 config.add_route(
381 name='edit_repo_perms_branch_delete',
381 name='edit_repo_perms_branch_delete',
382 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions/{rule_id}/delete',
382 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions/{rule_id}/delete',
383 repo_route=True)
383 repo_route=True)
384
384
385 # Maintenance
385 # Maintenance
386 config.add_route(
386 config.add_route(
387 name='edit_repo_maintenance',
387 name='edit_repo_maintenance',
388 pattern='/{repo_name:.*?[^/]}/settings/maintenance', repo_route=True)
388 pattern='/{repo_name:.*?[^/]}/settings/maintenance', repo_route=True)
389
389
390 config.add_route(
390 config.add_route(
391 name='edit_repo_maintenance_execute',
391 name='edit_repo_maintenance_execute',
392 pattern='/{repo_name:.*?[^/]}/settings/maintenance/execute', repo_route=True)
392 pattern='/{repo_name:.*?[^/]}/settings/maintenance/execute', repo_route=True)
393
393
394 # Fields
394 # Fields
395 config.add_route(
395 config.add_route(
396 name='edit_repo_fields',
396 name='edit_repo_fields',
397 pattern='/{repo_name:.*?[^/]}/settings/fields', repo_route=True)
397 pattern='/{repo_name:.*?[^/]}/settings/fields', repo_route=True)
398 config.add_route(
398 config.add_route(
399 name='edit_repo_fields_create',
399 name='edit_repo_fields_create',
400 pattern='/{repo_name:.*?[^/]}/settings/fields/create', repo_route=True)
400 pattern='/{repo_name:.*?[^/]}/settings/fields/create', repo_route=True)
401 config.add_route(
401 config.add_route(
402 name='edit_repo_fields_delete',
402 name='edit_repo_fields_delete',
403 pattern='/{repo_name:.*?[^/]}/settings/fields/{field_id}/delete', repo_route=True)
403 pattern='/{repo_name:.*?[^/]}/settings/fields/{field_id}/delete', repo_route=True)
404
404
405 # Locking
405 # Locking
406 config.add_route(
406 config.add_route(
407 name='repo_edit_toggle_locking',
407 name='repo_edit_toggle_locking',
408 pattern='/{repo_name:.*?[^/]}/settings/toggle_locking', repo_route=True)
408 pattern='/{repo_name:.*?[^/]}/settings/toggle_locking', repo_route=True)
409
409
410 # Remote
410 # Remote
411 config.add_route(
411 config.add_route(
412 name='edit_repo_remote',
412 name='edit_repo_remote',
413 pattern='/{repo_name:.*?[^/]}/settings/remote', repo_route=True)
413 pattern='/{repo_name:.*?[^/]}/settings/remote', repo_route=True)
414 config.add_route(
414 config.add_route(
415 name='edit_repo_remote_pull',
415 name='edit_repo_remote_pull',
416 pattern='/{repo_name:.*?[^/]}/settings/remote/pull', repo_route=True)
416 pattern='/{repo_name:.*?[^/]}/settings/remote/pull', repo_route=True)
417 config.add_route(
417 config.add_route(
418 name='edit_repo_remote_push',
418 name='edit_repo_remote_push',
419 pattern='/{repo_name:.*?[^/]}/settings/remote/push', repo_route=True)
419 pattern='/{repo_name:.*?[^/]}/settings/remote/push', repo_route=True)
420
420
421 # Statistics
421 # Statistics
422 config.add_route(
422 config.add_route(
423 name='edit_repo_statistics',
423 name='edit_repo_statistics',
424 pattern='/{repo_name:.*?[^/]}/settings/statistics', repo_route=True)
424 pattern='/{repo_name:.*?[^/]}/settings/statistics', repo_route=True)
425 config.add_route(
425 config.add_route(
426 name='edit_repo_statistics_reset',
426 name='edit_repo_statistics_reset',
427 pattern='/{repo_name:.*?[^/]}/settings/statistics/update', repo_route=True)
427 pattern='/{repo_name:.*?[^/]}/settings/statistics/update', repo_route=True)
428
428
429 # Issue trackers
429 # Issue trackers
430 config.add_route(
430 config.add_route(
431 name='edit_repo_issuetracker',
431 name='edit_repo_issuetracker',
432 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers', repo_route=True)
432 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers', repo_route=True)
433 config.add_route(
433 config.add_route(
434 name='edit_repo_issuetracker_test',
434 name='edit_repo_issuetracker_test',
435 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/test', repo_route=True)
435 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/test', repo_route=True)
436 config.add_route(
436 config.add_route(
437 name='edit_repo_issuetracker_delete',
437 name='edit_repo_issuetracker_delete',
438 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/delete', repo_route=True)
438 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/delete', repo_route=True)
439 config.add_route(
439 config.add_route(
440 name='edit_repo_issuetracker_update',
440 name='edit_repo_issuetracker_update',
441 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/update', repo_route=True)
441 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/update', repo_route=True)
442
442
443 # VCS Settings
443 # VCS Settings
444 config.add_route(
444 config.add_route(
445 name='edit_repo_vcs',
445 name='edit_repo_vcs',
446 pattern='/{repo_name:.*?[^/]}/settings/vcs', repo_route=True)
446 pattern='/{repo_name:.*?[^/]}/settings/vcs', repo_route=True)
447 config.add_route(
447 config.add_route(
448 name='edit_repo_vcs_update',
448 name='edit_repo_vcs_update',
449 pattern='/{repo_name:.*?[^/]}/settings/vcs/update', repo_route=True)
449 pattern='/{repo_name:.*?[^/]}/settings/vcs/update', repo_route=True)
450
450
451 # svn pattern
451 # svn pattern
452 config.add_route(
452 config.add_route(
453 name='edit_repo_vcs_svn_pattern_delete',
453 name='edit_repo_vcs_svn_pattern_delete',
454 pattern='/{repo_name:.*?[^/]}/settings/vcs/svn_pattern/delete', repo_route=True)
454 pattern='/{repo_name:.*?[^/]}/settings/vcs/svn_pattern/delete', repo_route=True)
455
455
456 # Repo Review Rules (EE feature)
456 # Repo Review Rules (EE feature)
457 config.add_route(
457 config.add_route(
458 name='repo_reviewers',
458 name='repo_reviewers',
459 pattern='/{repo_name:.*?[^/]}/settings/review/rules', repo_route=True)
459 pattern='/{repo_name:.*?[^/]}/settings/review/rules', repo_route=True)
460
460
461 config.add_route(
461 config.add_route(
462 name='repo_default_reviewers_data',
462 name='repo_default_reviewers_data',
463 pattern='/{repo_name:.*?[^/]}/settings/review/default-reviewers', repo_route=True)
463 pattern='/{repo_name:.*?[^/]}/settings/review/default-reviewers', repo_route=True)
464
464
465 # Repo Automation (EE feature)
465 # Repo Automation (EE feature)
466 config.add_route(
466 config.add_route(
467 name='repo_automation',
467 name='repo_automation',
468 pattern='/{repo_name:.*?[^/]}/settings/automation', repo_route=True)
468 pattern='/{repo_name:.*?[^/]}/settings/automation', repo_route=True)
469
469
470 # Strip
470 # Strip
471 config.add_route(
471 config.add_route(
472 name='edit_repo_strip',
472 name='edit_repo_strip',
473 pattern='/{repo_name:.*?[^/]}/settings/strip', repo_route=True)
473 pattern='/{repo_name:.*?[^/]}/settings/strip', repo_route=True)
474
474
475 config.add_route(
475 config.add_route(
476 name='strip_check',
476 name='strip_check',
477 pattern='/{repo_name:.*?[^/]}/settings/strip_check', repo_route=True)
477 pattern='/{repo_name:.*?[^/]}/settings/strip_check', repo_route=True)
478
478
479 config.add_route(
479 config.add_route(
480 name='strip_execute',
480 name='strip_execute',
481 pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True)
481 pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True)
482
482
483 # Audit logs
483 # Audit logs
484 config.add_route(
484 config.add_route(
485 name='edit_repo_audit_logs',
485 name='edit_repo_audit_logs',
486 pattern='/{repo_name:.*?[^/]}/settings/audit_logs', repo_route=True)
486 pattern='/{repo_name:.*?[^/]}/settings/audit_logs', repo_route=True)
487
487
488 # ATOM/RSS Feed
488 # ATOM/RSS Feed, shouldn't contain slashes for outlook compatibility
489 config.add_route(
489 config.add_route(
490 name='rss_feed_home',
490 name='rss_feed_home',
491 pattern='/{repo_name:.*?[^/]}/feed-rss', repo_route=True)
492
493 config.add_route(
494 name='atom_feed_home',
495 pattern='/{repo_name:.*?[^/]}/feed-atom', repo_route=True)
496
497 config.add_route(
498 name='rss_feed_home_old',
491 pattern='/{repo_name:.*?[^/]}/feed/rss', repo_route=True)
499 pattern='/{repo_name:.*?[^/]}/feed/rss', repo_route=True)
492
500
493 config.add_route(
501 config.add_route(
494 name='atom_feed_home',
502 name='atom_feed_home_old',
495 pattern='/{repo_name:.*?[^/]}/feed/atom', repo_route=True)
503 pattern='/{repo_name:.*?[^/]}/feed/atom', repo_route=True)
496
504
497 # NOTE(marcink): needs to be at the end for catch-all
505 # NOTE(marcink): needs to be at the end for catch-all
498 add_route_with_slash(
506 add_route_with_slash(
499 config,
507 config,
500 name='repo_summary',
508 name='repo_summary',
501 pattern='/{repo_name:.*?[^/]}', repo_route=True)
509 pattern='/{repo_name:.*?[^/]}', repo_route=True)
502
510
503 # Scan module for configuration decorators.
511 # Scan module for configuration decorators.
504 config.scan('.views', ignore='.tests')
512 config.scan('.views', ignore='.tests')
@@ -1,99 +1,137 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 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 pytest
21 import pytest
22 from rhodecode.model.auth_token import AuthTokenModel
22 from rhodecode.model.auth_token import AuthTokenModel
23 from rhodecode.tests import TestController
23 from rhodecode.tests import TestController
24
24
25
25
26 def route_path(name, params=None, **kwargs):
26 def route_path(name, params=None, **kwargs):
27 import urllib
27 import urllib
28
28
29 base_url = {
29 base_url = {
30 'rss_feed_home': '/{repo_name}/feed/rss',
30 'rss_feed_home': '/{repo_name}/feed-rss',
31 'atom_feed_home': '/{repo_name}/feed/atom',
31 'atom_feed_home': '/{repo_name}/feed-atom',
32 'rss_feed_home_old': '/{repo_name}/feed/rss',
33 'atom_feed_home_old': '/{repo_name}/feed/atom',
32 }[name].format(**kwargs)
34 }[name].format(**kwargs)
33
35
34 if params:
36 if params:
35 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
37 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
36 return base_url
38 return base_url
37
39
38
40
39 class TestFeedView(TestController):
41 class TestFeedView(TestController):
40
42
41 @pytest.mark.parametrize("feed_type,response_types,content_type",[
43 @pytest.mark.parametrize("feed_type,response_types,content_type",[
42 ('rss', ['<rss version="2.0">'],
44 ('rss', ['<rss version="2.0">'],
43 "application/rss+xml"),
45 "application/rss+xml"),
44 ('atom', ['xmlns="http://www.w3.org/2005/Atom"', 'xml:lang="en-us"'],
46 ('atom', ['xmlns="http://www.w3.org/2005/Atom"', 'xml:lang="en-us"'],
45 "application/atom+xml"),
47 "application/atom+xml"),
46 ])
48 ])
47 def test_feed(self, backend, feed_type, response_types, content_type):
49 def test_feed(self, backend, feed_type, response_types, content_type):
48 self.log_user()
50 self.log_user()
49 response = self.app.get(
51 response = self.app.get(
50 route_path('{}_feed_home'.format(feed_type),
52 route_path('{}_feed_home'.format(feed_type),
51 repo_name=backend.repo_name))
53 repo_name=backend.repo_name))
52
54
53 for content in response_types:
55 for content in response_types:
54 response.mustcontain(content)
56 response.mustcontain(content)
55
57
56 assert response.content_type == content_type
58 assert response.content_type == content_type
57
59
58 @pytest.mark.parametrize("feed_type, content_type", [
60 @pytest.mark.parametrize("feed_type, content_type", [
59 ('rss', "application/rss+xml"),
61 ('rss', "application/rss+xml"),
60 ('atom', "application/atom+xml")
62 ('atom', "application/atom+xml")
61 ])
63 ])
62 def test_feed_with_auth_token(
64 def test_feed_with_auth_token(
63 self, backend, user_admin, feed_type, content_type):
65 self, backend, user_admin, feed_type, content_type):
64 auth_token = user_admin.feed_token
66 auth_token = user_admin.feed_token
65 assert auth_token != ''
67 assert auth_token != ''
66
68
67 response = self.app.get(
69 response = self.app.get(
68 route_path(
70 route_path(
69 '{}_feed_home'.format(feed_type),
71 '{}_feed_home'.format(feed_type),
70 repo_name=backend.repo_name,
72 repo_name=backend.repo_name,
71 params=dict(auth_token=auth_token)),
73 params=dict(auth_token=auth_token)),
72 status=200)
74 status=200)
73
75
74 assert response.content_type == content_type
76 assert response.content_type == content_type
75
77
78 @pytest.mark.parametrize("feed_type, content_type", [
79 ('rss', "application/rss+xml"),
80 ('atom', "application/atom+xml")
81 ])
82 def test_feed_with_auth_token_by_uid(
83 self, backend, user_admin, feed_type, content_type):
84 auth_token = user_admin.feed_token
85 assert auth_token != ''
86
87 response = self.app.get(
88 route_path(
89 '{}_feed_home'.format(feed_type),
90 repo_name='_{}'.format(backend.repo.repo_id),
91 params=dict(auth_token=auth_token)),
92 status=200)
93
94 assert response.content_type == content_type
95
96 @pytest.mark.parametrize("feed_type, content_type", [
97 ('rss', "application/rss+xml"),
98 ('atom', "application/atom+xml")
99 ])
100 def test_feed_old_urls_with_auth_token(
101 self, backend, user_admin, feed_type, content_type):
102 auth_token = user_admin.feed_token
103 assert auth_token != ''
104
105 response = self.app.get(
106 route_path(
107 '{}_feed_home_old'.format(feed_type),
108 repo_name=backend.repo_name,
109 params=dict(auth_token=auth_token)),
110 status=200)
111
112 assert response.content_type == content_type
113
76 @pytest.mark.parametrize("feed_type", ['rss', 'atom'])
114 @pytest.mark.parametrize("feed_type", ['rss', 'atom'])
77 def test_feed_with_auth_token_of_wrong_type(
115 def test_feed_with_auth_token_of_wrong_type(
78 self, backend, user_util, feed_type):
116 self, backend, user_util, feed_type):
79 user = user_util.create_user()
117 user = user_util.create_user()
80 auth_token = AuthTokenModel().create(
118 auth_token = AuthTokenModel().create(
81 user.user_id, 'test-token', -1, AuthTokenModel.cls.ROLE_API)
119 user.user_id, 'test-token', -1, AuthTokenModel.cls.ROLE_API)
82 auth_token = auth_token.api_key
120 auth_token = auth_token.api_key
83
121
84 self.app.get(
122 self.app.get(
85 route_path(
123 route_path(
86 '{}_feed_home'.format(feed_type),
124 '{}_feed_home'.format(feed_type),
87 repo_name=backend.repo_name,
125 repo_name=backend.repo_name,
88 params=dict(auth_token=auth_token)),
126 params=dict(auth_token=auth_token)),
89 status=302)
127 status=302)
90
128
91 auth_token = AuthTokenModel().create(
129 auth_token = AuthTokenModel().create(
92 user.user_id, 'test-token', -1, AuthTokenModel.cls.ROLE_FEED)
130 user.user_id, 'test-token', -1, AuthTokenModel.cls.ROLE_FEED)
93 auth_token = auth_token.api_key
131 auth_token = auth_token.api_key
94 self.app.get(
132 self.app.get(
95 route_path(
133 route_path(
96 '{}_feed_home'.format(feed_type),
134 '{}_feed_home'.format(feed_type),
97 repo_name=backend.repo_name,
135 repo_name=backend.repo_name,
98 params=dict(auth_token=auth_token)),
136 params=dict(auth_token=auth_token)),
99 status=200)
137 status=200)
@@ -1,238 +1,242 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2019 RhodeCode GmbH
3 # Copyright (C) 2017-2019 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 import pytz
20 import pytz
21 import logging
21 import logging
22
22
23 from pyramid.view import view_config
23 from pyramid.view import view_config
24 from pyramid.response import Response
24 from pyramid.response import Response
25 from webhelpers.feedgenerator import Rss201rev2Feed, Atom1Feed
25 from webhelpers.feedgenerator import Rss201rev2Feed, Atom1Feed
26
26
27 from rhodecode.apps._base import RepoAppView
27 from rhodecode.apps._base import RepoAppView
28 from rhodecode.lib import audit_logger
28 from rhodecode.lib import audit_logger
29 from rhodecode.lib import rc_cache
29 from rhodecode.lib import rc_cache
30 from rhodecode.lib import helpers as h
30 from rhodecode.lib import helpers as h
31 from rhodecode.lib.auth import (
31 from rhodecode.lib.auth import (
32 LoginRequired, HasRepoPermissionAnyDecorator)
32 LoginRequired, HasRepoPermissionAnyDecorator)
33 from rhodecode.lib.diffs import DiffProcessor, LimitedDiffContainer
33 from rhodecode.lib.diffs import DiffProcessor, LimitedDiffContainer
34 from rhodecode.lib.utils2 import str2bool, safe_int, md5_safe
34 from rhodecode.lib.utils2 import str2bool, safe_int, md5_safe
35 from rhodecode.model.db import UserApiKeys, CacheKey
35 from rhodecode.model.db import UserApiKeys, CacheKey
36
36
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
39
39
40 class RepoFeedView(RepoAppView):
40 class RepoFeedView(RepoAppView):
41 def load_default_context(self):
41 def load_default_context(self):
42 c = self._get_local_tmpl_context()
42 c = self._get_local_tmpl_context()
43
44
45 self._load_defaults()
43 self._load_defaults()
46 return c
44 return c
47
45
48 def _get_config(self):
46 def _get_config(self):
49 import rhodecode
47 import rhodecode
50 config = rhodecode.CONFIG
48 config = rhodecode.CONFIG
51
49
52 return {
50 return {
53 'language': 'en-us',
51 'language': 'en-us',
54 'feed_ttl': '5', # TTL of feed,
52 'feed_ttl': '5', # TTL of feed,
55 'feed_include_diff':
53 'feed_include_diff':
56 str2bool(config.get('rss_include_diff', False)),
54 str2bool(config.get('rss_include_diff', False)),
57 'feed_items_per_page':
55 'feed_items_per_page':
58 safe_int(config.get('rss_items_per_page', 20)),
56 safe_int(config.get('rss_items_per_page', 20)),
59 'feed_diff_limit':
57 'feed_diff_limit':
60 # we need to protect from parsing huge diffs here other way
58 # we need to protect from parsing huge diffs here other way
61 # we can kill the server
59 # we can kill the server
62 safe_int(config.get('rss_cut_off_limit', 32 * 1024)),
60 safe_int(config.get('rss_cut_off_limit', 32 * 1024)),
63 }
61 }
64
62
65 def _load_defaults(self):
63 def _load_defaults(self):
66 _ = self.request.translate
64 _ = self.request.translate
67 config = self._get_config()
65 config = self._get_config()
68 # common values for feeds
66 # common values for feeds
69 self.description = _('Changes on %s repository')
67 self.description = _('Changes on %s repository')
70 self.title = self.title = _('%s %s feed') % (self.db_repo_name, '%s')
68 self.title = self.title = _('%s %s feed') % (self.db_repo_name, '%s')
71 self.language = config["language"]
69 self.language = config["language"]
72 self.ttl = config["feed_ttl"]
70 self.ttl = config["feed_ttl"]
73 self.feed_include_diff = config['feed_include_diff']
71 self.feed_include_diff = config['feed_include_diff']
74 self.feed_diff_limit = config['feed_diff_limit']
72 self.feed_diff_limit = config['feed_diff_limit']
75 self.feed_items_per_page = config['feed_items_per_page']
73 self.feed_items_per_page = config['feed_items_per_page']
76
74
77 def _changes(self, commit):
75 def _changes(self, commit):
78 diff_processor = DiffProcessor(
76 diff_processor = DiffProcessor(
79 commit.diff(), diff_limit=self.feed_diff_limit)
77 commit.diff(), diff_limit=self.feed_diff_limit)
80 _parsed = diff_processor.prepare(inline_diff=False)
78 _parsed = diff_processor.prepare(inline_diff=False)
81 limited_diff = isinstance(_parsed, LimitedDiffContainer)
79 limited_diff = isinstance(_parsed, LimitedDiffContainer)
82
80
83 return diff_processor, _parsed, limited_diff
81 return diff_processor, _parsed, limited_diff
84
82
85 def _get_title(self, commit):
83 def _get_title(self, commit):
86 return h.shorter(commit.message, 160)
84 return h.shorter(commit.message, 160)
87
85
88 def _get_description(self, commit):
86 def _get_description(self, commit):
89 _renderer = self.request.get_partial_renderer(
87 _renderer = self.request.get_partial_renderer(
90 'rhodecode:templates/feed/atom_feed_entry.mako')
88 'rhodecode:templates/feed/atom_feed_entry.mako')
91 diff_processor, parsed_diff, limited_diff = self._changes(commit)
89 diff_processor, parsed_diff, limited_diff = self._changes(commit)
92 filtered_parsed_diff, has_hidden_changes = self.path_filter.filter_patchset(parsed_diff)
90 filtered_parsed_diff, has_hidden_changes = self.path_filter.filter_patchset(parsed_diff)
93 return _renderer(
91 return _renderer(
94 'body',
92 'body',
95 commit=commit,
93 commit=commit,
96 parsed_diff=filtered_parsed_diff,
94 parsed_diff=filtered_parsed_diff,
97 limited_diff=limited_diff,
95 limited_diff=limited_diff,
98 feed_include_diff=self.feed_include_diff,
96 feed_include_diff=self.feed_include_diff,
99 diff_processor=diff_processor,
97 diff_processor=diff_processor,
100 has_hidden_changes=has_hidden_changes
98 has_hidden_changes=has_hidden_changes
101 )
99 )
102
100
103 def _set_timezone(self, date, tzinfo=pytz.utc):
101 def _set_timezone(self, date, tzinfo=pytz.utc):
104 if not getattr(date, "tzinfo", None):
102 if not getattr(date, "tzinfo", None):
105 date.replace(tzinfo=tzinfo)
103 date.replace(tzinfo=tzinfo)
106 return date
104 return date
107
105
108 def _get_commits(self):
106 def _get_commits(self):
109 return list(self.rhodecode_vcs_repo[-self.feed_items_per_page:])
107 return list(self.rhodecode_vcs_repo[-self.feed_items_per_page:])
110
108
111 def uid(self, repo_id, commit_id):
109 def uid(self, repo_id, commit_id):
112 return '{}:{}'.format(md5_safe(repo_id), md5_safe(commit_id))
110 return '{}:{}'.format(md5_safe(repo_id), md5_safe(commit_id))
113
111
114 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
112 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
115 @HasRepoPermissionAnyDecorator(
113 @HasRepoPermissionAnyDecorator(
116 'repository.read', 'repository.write', 'repository.admin')
114 'repository.read', 'repository.write', 'repository.admin')
117 @view_config(
115 @view_config(
118 route_name='atom_feed_home', request_method='GET',
116 route_name='atom_feed_home', request_method='GET',
119 renderer=None)
117 renderer=None)
118 @view_config(
119 route_name='atom_feed_home_old', request_method='GET',
120 renderer=None)
120 def atom(self):
121 def atom(self):
121 """
122 """
122 Produce an atom-1.0 feed via feedgenerator module
123 Produce an atom-1.0 feed via feedgenerator module
123 """
124 """
124 self.load_default_context()
125 self.load_default_context()
125
126
126 cache_namespace_uid = 'cache_repo_instance.{}_{}'.format(
127 cache_namespace_uid = 'cache_repo_instance.{}_{}'.format(
127 self.db_repo.repo_id, CacheKey.CACHE_TYPE_FEED)
128 self.db_repo.repo_id, CacheKey.CACHE_TYPE_FEED)
128 invalidation_namespace = CacheKey.REPO_INVALIDATION_NAMESPACE.format(
129 invalidation_namespace = CacheKey.REPO_INVALIDATION_NAMESPACE.format(
129 repo_id=self.db_repo.repo_id)
130 repo_id=self.db_repo.repo_id)
130
131
131 region = rc_cache.get_or_create_region('cache_repo_longterm',
132 region = rc_cache.get_or_create_region('cache_repo_longterm',
132 cache_namespace_uid)
133 cache_namespace_uid)
133
134
134 condition = not self.path_filter.is_enabled
135 condition = not self.path_filter.is_enabled
135
136
136 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
137 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
137 condition=condition)
138 condition=condition)
138 def generate_atom_feed(repo_id, _repo_name, _feed_type):
139 def generate_atom_feed(repo_id, _repo_name, _feed_type):
139 feed = Atom1Feed(
140 feed = Atom1Feed(
140 title=self.title % _repo_name,
141 title=self.title % _repo_name,
141 link=h.route_url('repo_summary', repo_name=_repo_name),
142 link=h.route_url('repo_summary', repo_name=_repo_name),
142 description=self.description % _repo_name,
143 description=self.description % _repo_name,
143 language=self.language,
144 language=self.language,
144 ttl=self.ttl
145 ttl=self.ttl
145 )
146 )
146
147
147 for commit in reversed(self._get_commits()):
148 for commit in reversed(self._get_commits()):
148 date = self._set_timezone(commit.date)
149 date = self._set_timezone(commit.date)
149 feed.add_item(
150 feed.add_item(
150 unique_id=self.uid(repo_id, commit.raw_id),
151 unique_id=self.uid(repo_id, commit.raw_id),
151 title=self._get_title(commit),
152 title=self._get_title(commit),
152 author_name=commit.author,
153 author_name=commit.author,
153 description=self._get_description(commit),
154 description=self._get_description(commit),
154 link=h.route_url(
155 link=h.route_url(
155 'repo_commit', repo_name=_repo_name,
156 'repo_commit', repo_name=_repo_name,
156 commit_id=commit.raw_id),
157 commit_id=commit.raw_id),
157 pubdate=date,)
158 pubdate=date,)
158
159
159 return feed.mime_type, feed.writeString('utf-8')
160 return feed.mime_type, feed.writeString('utf-8')
160
161
161 inv_context_manager = rc_cache.InvalidationContext(
162 inv_context_manager = rc_cache.InvalidationContext(
162 uid=cache_namespace_uid, invalidation_namespace=invalidation_namespace)
163 uid=cache_namespace_uid, invalidation_namespace=invalidation_namespace)
163 with inv_context_manager as invalidation_context:
164 with inv_context_manager as invalidation_context:
164 args = (self.db_repo.repo_id, self.db_repo.repo_name, 'atom',)
165 args = (self.db_repo.repo_id, self.db_repo.repo_name, 'atom',)
165 # re-compute and store cache if we get invalidate signal
166 # re-compute and store cache if we get invalidate signal
166 if invalidation_context.should_invalidate():
167 if invalidation_context.should_invalidate():
167 mime_type, feed = generate_atom_feed.refresh(*args)
168 mime_type, feed = generate_atom_feed.refresh(*args)
168 else:
169 else:
169 mime_type, feed = generate_atom_feed(*args)
170 mime_type, feed = generate_atom_feed(*args)
170
171
171 log.debug('Repo ATOM feed computed in %.3fs',
172 log.debug('Repo ATOM feed computed in %.3fs',
172 inv_context_manager.compute_time)
173 inv_context_manager.compute_time)
173
174
174 response = Response(feed)
175 response = Response(feed)
175 response.content_type = mime_type
176 response.content_type = mime_type
176 return response
177 return response
177
178
178 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
179 @LoginRequired(auth_token_access=[UserApiKeys.ROLE_FEED])
179 @HasRepoPermissionAnyDecorator(
180 @HasRepoPermissionAnyDecorator(
180 'repository.read', 'repository.write', 'repository.admin')
181 'repository.read', 'repository.write', 'repository.admin')
181 @view_config(
182 @view_config(
182 route_name='rss_feed_home', request_method='GET',
183 route_name='rss_feed_home', request_method='GET',
183 renderer=None)
184 renderer=None)
185 @view_config(
186 route_name='rss_feed_home_old', request_method='GET',
187 renderer=None)
184 def rss(self):
188 def rss(self):
185 """
189 """
186 Produce an rss2 feed via feedgenerator module
190 Produce an rss2 feed via feedgenerator module
187 """
191 """
188 self.load_default_context()
192 self.load_default_context()
189
193
190 cache_namespace_uid = 'cache_repo_instance.{}_{}'.format(
194 cache_namespace_uid = 'cache_repo_instance.{}_{}'.format(
191 self.db_repo.repo_id, CacheKey.CACHE_TYPE_FEED)
195 self.db_repo.repo_id, CacheKey.CACHE_TYPE_FEED)
192 invalidation_namespace = CacheKey.REPO_INVALIDATION_NAMESPACE.format(
196 invalidation_namespace = CacheKey.REPO_INVALIDATION_NAMESPACE.format(
193 repo_id=self.db_repo.repo_id)
197 repo_id=self.db_repo.repo_id)
194 region = rc_cache.get_or_create_region('cache_repo_longterm',
198 region = rc_cache.get_or_create_region('cache_repo_longterm',
195 cache_namespace_uid)
199 cache_namespace_uid)
196
200
197 condition = not self.path_filter.is_enabled
201 condition = not self.path_filter.is_enabled
198
202
199 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
203 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
200 condition=condition)
204 condition=condition)
201 def generate_rss_feed(repo_id, _repo_name, _feed_type):
205 def generate_rss_feed(repo_id, _repo_name, _feed_type):
202 feed = Rss201rev2Feed(
206 feed = Rss201rev2Feed(
203 title=self.title % _repo_name,
207 title=self.title % _repo_name,
204 link=h.route_url('repo_summary', repo_name=_repo_name),
208 link=h.route_url('repo_summary', repo_name=_repo_name),
205 description=self.description % _repo_name,
209 description=self.description % _repo_name,
206 language=self.language,
210 language=self.language,
207 ttl=self.ttl
211 ttl=self.ttl
208 )
212 )
209
213
210 for commit in reversed(self._get_commits()):
214 for commit in reversed(self._get_commits()):
211 date = self._set_timezone(commit.date)
215 date = self._set_timezone(commit.date)
212 feed.add_item(
216 feed.add_item(
213 unique_id=self.uid(repo_id, commit.raw_id),
217 unique_id=self.uid(repo_id, commit.raw_id),
214 title=self._get_title(commit),
218 title=self._get_title(commit),
215 author_name=commit.author,
219 author_name=commit.author,
216 description=self._get_description(commit),
220 description=self._get_description(commit),
217 link=h.route_url(
221 link=h.route_url(
218 'repo_commit', repo_name=_repo_name,
222 'repo_commit', repo_name=_repo_name,
219 commit_id=commit.raw_id),
223 commit_id=commit.raw_id),
220 pubdate=date,)
224 pubdate=date,)
221
225
222 return feed.mime_type, feed.writeString('utf-8')
226 return feed.mime_type, feed.writeString('utf-8')
223
227
224 inv_context_manager = rc_cache.InvalidationContext(
228 inv_context_manager = rc_cache.InvalidationContext(
225 uid=cache_namespace_uid, invalidation_namespace=invalidation_namespace)
229 uid=cache_namespace_uid, invalidation_namespace=invalidation_namespace)
226 with inv_context_manager as invalidation_context:
230 with inv_context_manager as invalidation_context:
227 args = (self.db_repo.repo_id, self.db_repo.repo_name, 'rss',)
231 args = (self.db_repo.repo_id, self.db_repo.repo_name, 'rss',)
228 # re-compute and store cache if we get invalidate signal
232 # re-compute and store cache if we get invalidate signal
229 if invalidation_context.should_invalidate():
233 if invalidation_context.should_invalidate():
230 mime_type, feed = generate_rss_feed.refresh(*args)
234 mime_type, feed = generate_rss_feed.refresh(*args)
231 else:
235 else:
232 mime_type, feed = generate_rss_feed(*args)
236 mime_type, feed = generate_rss_feed(*args)
233 log.debug(
237 log.debug(
234 'Repo RSS feed computed in %.3fs', inv_context_manager.compute_time)
238 'Repo RSS feed computed in %.3fs', inv_context_manager.compute_time)
235
239
236 response = Response(feed)
240 response = Response(feed)
237 response.content_type = mime_type
241 response.content_type = mime_type
238 return response
242 return response
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,376 +1,378 b''
1
1
2 /******************************************************************************
2 /******************************************************************************
3 * *
3 * *
4 * DO NOT CHANGE THIS FILE MANUALLY *
4 * DO NOT CHANGE THIS FILE MANUALLY *
5 * *
5 * *
6 * *
6 * *
7 * This file is automatically generated when the app starts up with *
7 * This file is automatically generated when the app starts up with *
8 * generate_js_files = true *
8 * generate_js_files = true *
9 * *
9 * *
10 * To add a route here pass jsroute=True to the route definition in the app *
10 * To add a route here pass jsroute=True to the route definition in the app *
11 * *
11 * *
12 ******************************************************************************/
12 ******************************************************************************/
13 function registerRCRoutes() {
13 function registerRCRoutes() {
14 // routes registration
14 // routes registration
15 pyroutes.register('favicon', '/favicon.ico', []);
15 pyroutes.register('favicon', '/favicon.ico', []);
16 pyroutes.register('robots', '/robots.txt', []);
16 pyroutes.register('robots', '/robots.txt', []);
17 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
17 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
18 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
18 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
19 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
19 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
20 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
20 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
21 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
21 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
22 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']);
22 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']);
23 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']);
23 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']);
24 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
24 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
25 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
25 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
26 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
26 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
27 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
27 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
28 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
28 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
29 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
29 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
30 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
30 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
31 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
31 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
32 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
32 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
33 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
33 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
34 pyroutes.register('ops_error_test', '/_admin/ops/error', []);
34 pyroutes.register('ops_error_test', '/_admin/ops/error', []);
35 pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []);
35 pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []);
36 pyroutes.register('ops_ping_legacy', '/_admin/ping', []);
36 pyroutes.register('ops_ping_legacy', '/_admin/ping', []);
37 pyroutes.register('ops_error_test_legacy', '/_admin/error_test', []);
37 pyroutes.register('ops_error_test_legacy', '/_admin/error_test', []);
38 pyroutes.register('admin_home', '/_admin', []);
38 pyroutes.register('admin_home', '/_admin', []);
39 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
39 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
40 pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']);
40 pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']);
41 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
41 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
42 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
42 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
43 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
43 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
44 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
44 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
45 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
45 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
46 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
46 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
47 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
47 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
48 pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []);
48 pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []);
49 pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions/delete', []);
49 pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions/delete', []);
50 pyroutes.register('admin_settings_exception_tracker_show', '/_admin/settings/exceptions/%(exception_id)s', ['exception_id']);
50 pyroutes.register('admin_settings_exception_tracker_show', '/_admin/settings/exceptions/%(exception_id)s', ['exception_id']);
51 pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']);
51 pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']);
52 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
52 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
53 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
53 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
54 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
54 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
55 pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []);
55 pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []);
56 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
56 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
57 pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []);
57 pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []);
58 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
58 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
59 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
59 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
60 pyroutes.register('admin_settings', '/_admin/settings', []);
60 pyroutes.register('admin_settings', '/_admin/settings', []);
61 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
61 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
62 pyroutes.register('admin_settings_global', '/_admin/settings/global', []);
62 pyroutes.register('admin_settings_global', '/_admin/settings/global', []);
63 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
63 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
64 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
64 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
65 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
65 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
66 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
66 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
67 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
67 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
68 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
68 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
69 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
69 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
70 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
70 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
71 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
71 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
72 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
72 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
73 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
73 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
74 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
74 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
75 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
75 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
76 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
76 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
77 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
77 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
78 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
78 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
79 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
79 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
80 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
80 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
81 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
81 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
82 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
82 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
83 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
83 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
84 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
84 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
85 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
85 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
86 pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []);
86 pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []);
87 pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []);
87 pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []);
88 pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []);
88 pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []);
89 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
89 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
90 pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []);
90 pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []);
91 pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []);
91 pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []);
92 pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []);
92 pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []);
93 pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []);
93 pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []);
94 pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []);
94 pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []);
95 pyroutes.register('users', '/_admin/users', []);
95 pyroutes.register('users', '/_admin/users', []);
96 pyroutes.register('users_data', '/_admin/users_data', []);
96 pyroutes.register('users_data', '/_admin/users_data', []);
97 pyroutes.register('users_create', '/_admin/users/create', []);
97 pyroutes.register('users_create', '/_admin/users/create', []);
98 pyroutes.register('users_new', '/_admin/users/new', []);
98 pyroutes.register('users_new', '/_admin/users/new', []);
99 pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']);
99 pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']);
100 pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']);
100 pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']);
101 pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']);
101 pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']);
102 pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']);
102 pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']);
103 pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']);
103 pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']);
104 pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']);
104 pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']);
105 pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']);
105 pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']);
106 pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']);
106 pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']);
107 pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']);
107 pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']);
108 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
108 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
109 pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']);
109 pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']);
110 pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']);
110 pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']);
111 pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']);
111 pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']);
112 pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']);
112 pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']);
113 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
113 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
114 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
114 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
115 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
115 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
116 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
116 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
117 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
117 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
118 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
118 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
119 pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']);
119 pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']);
120 pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']);
120 pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']);
121 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
121 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
122 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
122 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
123 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
123 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
124 pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']);
124 pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']);
125 pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']);
125 pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']);
126 pyroutes.register('user_groups', '/_admin/user_groups', []);
126 pyroutes.register('user_groups', '/_admin/user_groups', []);
127 pyroutes.register('user_groups_data', '/_admin/user_groups_data', []);
127 pyroutes.register('user_groups_data', '/_admin/user_groups_data', []);
128 pyroutes.register('user_groups_new', '/_admin/user_groups/new', []);
128 pyroutes.register('user_groups_new', '/_admin/user_groups/new', []);
129 pyroutes.register('user_groups_create', '/_admin/user_groups/create', []);
129 pyroutes.register('user_groups_create', '/_admin/user_groups/create', []);
130 pyroutes.register('repos', '/_admin/repos', []);
130 pyroutes.register('repos', '/_admin/repos', []);
131 pyroutes.register('repo_new', '/_admin/repos/new', []);
131 pyroutes.register('repo_new', '/_admin/repos/new', []);
132 pyroutes.register('repo_create', '/_admin/repos/create', []);
132 pyroutes.register('repo_create', '/_admin/repos/create', []);
133 pyroutes.register('repo_groups', '/_admin/repo_groups', []);
133 pyroutes.register('repo_groups', '/_admin/repo_groups', []);
134 pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []);
134 pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []);
135 pyroutes.register('repo_group_new', '/_admin/repo_group/new', []);
135 pyroutes.register('repo_group_new', '/_admin/repo_group/new', []);
136 pyroutes.register('repo_group_create', '/_admin/repo_group/create', []);
136 pyroutes.register('repo_group_create', '/_admin/repo_group/create', []);
137 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
137 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
138 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
138 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
139 pyroutes.register('channelstream_proxy', '/_channelstream', []);
139 pyroutes.register('channelstream_proxy', '/_channelstream', []);
140 pyroutes.register('upload_file', '/_file_store/upload', []);
140 pyroutes.register('upload_file', '/_file_store/upload', []);
141 pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']);
141 pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']);
142 pyroutes.register('logout', '/_admin/logout', []);
142 pyroutes.register('logout', '/_admin/logout', []);
143 pyroutes.register('reset_password', '/_admin/password_reset', []);
143 pyroutes.register('reset_password', '/_admin/password_reset', []);
144 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
144 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
145 pyroutes.register('home', '/', []);
145 pyroutes.register('home', '/', []);
146 pyroutes.register('user_autocomplete_data', '/_users', []);
146 pyroutes.register('user_autocomplete_data', '/_users', []);
147 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
147 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
148 pyroutes.register('repo_list_data', '/_repos', []);
148 pyroutes.register('repo_list_data', '/_repos', []);
149 pyroutes.register('repo_group_list_data', '/_repo_groups', []);
149 pyroutes.register('repo_group_list_data', '/_repo_groups', []);
150 pyroutes.register('goto_switcher_data', '/_goto_data', []);
150 pyroutes.register('goto_switcher_data', '/_goto_data', []);
151 pyroutes.register('markup_preview', '/_markup_preview', []);
151 pyroutes.register('markup_preview', '/_markup_preview', []);
152 pyroutes.register('file_preview', '/_file_preview', []);
152 pyroutes.register('file_preview', '/_file_preview', []);
153 pyroutes.register('store_user_session_value', '/_store_session_attr', []);
153 pyroutes.register('store_user_session_value', '/_store_session_attr', []);
154 pyroutes.register('journal', '/_admin/journal', []);
154 pyroutes.register('journal', '/_admin/journal', []);
155 pyroutes.register('journal_rss', '/_admin/journal/rss', []);
155 pyroutes.register('journal_rss', '/_admin/journal/rss', []);
156 pyroutes.register('journal_atom', '/_admin/journal/atom', []);
156 pyroutes.register('journal_atom', '/_admin/journal/atom', []);
157 pyroutes.register('journal_public', '/_admin/public_journal', []);
157 pyroutes.register('journal_public', '/_admin/public_journal', []);
158 pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []);
158 pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []);
159 pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []);
159 pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []);
160 pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
160 pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
161 pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
161 pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
162 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
162 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
163 pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
163 pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
164 pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
164 pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
165 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
165 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
166 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
166 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
167 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
167 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
168 pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
168 pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
169 pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
169 pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
170 pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
170 pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
171 pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
171 pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
172 pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
172 pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
173 pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
173 pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
174 pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
174 pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
175 pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
175 pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
176 pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
176 pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
177 pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
177 pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
178 pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
178 pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
179 pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
179 pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
180 pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
180 pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
181 pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
181 pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
182 pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']);
182 pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']);
183 pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']);
183 pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']);
184 pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
184 pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
185 pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
185 pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
186 pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
186 pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
187 pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
187 pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
188 pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']);
188 pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']);
189 pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
189 pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
190 pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
190 pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
191 pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
191 pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
192 pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
192 pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
193 pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
193 pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
194 pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
194 pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
195 pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
195 pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
196 pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
196 pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
197 pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
197 pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
198 pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
198 pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
199 pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
199 pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
200 pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
200 pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
201 pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
201 pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
202 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
202 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
203 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
203 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
204 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
204 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
205 pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']);
205 pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']);
206 pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
206 pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
207 pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']);
207 pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']);
208 pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
208 pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
209 pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']);
209 pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']);
210 pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
210 pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
211 pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']);
211 pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']);
212 pyroutes.register('repo_compare', '/%(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']);
212 pyroutes.register('repo_compare', '/%(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']);
213 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
213 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
214 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
214 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
215 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
215 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
216 pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']);
216 pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']);
217 pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']);
217 pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']);
218 pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']);
218 pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']);
219 pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']);
219 pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']);
220 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
220 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
221 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
221 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
222 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
222 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
223 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
223 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
224 pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']);
224 pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']);
225 pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']);
225 pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']);
226 pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']);
226 pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']);
227 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']);
227 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']);
228 pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']);
228 pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']);
229 pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']);
229 pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']);
230 pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']);
230 pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']);
231 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']);
231 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']);
232 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
232 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
233 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
233 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
234 pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']);
234 pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']);
235 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
235 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
236 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
236 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
237 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
237 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
238 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
238 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
239 pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']);
239 pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']);
240 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
240 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
241 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
241 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
242 pyroutes.register('edit_repo_perms_set_private', '/%(repo_name)s/settings/permissions/set_private', ['repo_name']);
242 pyroutes.register('edit_repo_perms_set_private', '/%(repo_name)s/settings/permissions/set_private', ['repo_name']);
243 pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
243 pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
244 pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
244 pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
245 pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']);
245 pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']);
246 pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']);
246 pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']);
247 pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']);
247 pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']);
248 pyroutes.register('repo_edit_toggle_locking', '/%(repo_name)s/settings/toggle_locking', ['repo_name']);
248 pyroutes.register('repo_edit_toggle_locking', '/%(repo_name)s/settings/toggle_locking', ['repo_name']);
249 pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']);
249 pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']);
250 pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']);
250 pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']);
251 pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']);
251 pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']);
252 pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']);
252 pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']);
253 pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']);
253 pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']);
254 pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']);
254 pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']);
255 pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']);
255 pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']);
256 pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']);
256 pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']);
257 pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']);
257 pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']);
258 pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']);
258 pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']);
259 pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']);
259 pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']);
260 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
260 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
261 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
261 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
262 pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']);
262 pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']);
263 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
263 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
264 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
264 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
265 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
265 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
266 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed/rss', ['repo_name']);
266 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed-rss', ['repo_name']);
267 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed/atom', ['repo_name']);
267 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed-atom', ['repo_name']);
268 pyroutes.register('rss_feed_home_old', '/%(repo_name)s/feed/rss', ['repo_name']);
269 pyroutes.register('atom_feed_home_old', '/%(repo_name)s/feed/atom', ['repo_name']);
268 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
270 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
269 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
271 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
270 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
272 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
271 pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']);
273 pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']);
272 pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']);
274 pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']);
273 pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']);
275 pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']);
274 pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']);
276 pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']);
275 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
277 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
276 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
278 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
277 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
279 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
278 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
280 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
279 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
281 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
280 pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']);
282 pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']);
281 pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']);
283 pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']);
282 pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']);
284 pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']);
283 pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']);
285 pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']);
284 pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']);
286 pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']);
285 pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']);
287 pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']);
286 pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']);
288 pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']);
287 pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']);
289 pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']);
288 pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']);
290 pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']);
289 pyroutes.register('search', '/_admin/search', []);
291 pyroutes.register('search', '/_admin/search', []);
290 pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']);
292 pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']);
291 pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']);
293 pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']);
292 pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']);
294 pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']);
293 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
295 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
294 pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']);
296 pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']);
295 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
297 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
296 pyroutes.register('my_account_edit', '/_admin/my_account/edit', []);
298 pyroutes.register('my_account_edit', '/_admin/my_account/edit', []);
297 pyroutes.register('my_account_update', '/_admin/my_account/update', []);
299 pyroutes.register('my_account_update', '/_admin/my_account/update', []);
298 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
300 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
299 pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []);
301 pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []);
300 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
302 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
301 pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []);
303 pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []);
302 pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []);
304 pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []);
303 pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []);
305 pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []);
304 pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []);
306 pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []);
305 pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []);
307 pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []);
306 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
308 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
307 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
309 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
308 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
310 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
309 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
311 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
310 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
312 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
311 pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []);
313 pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []);
312 pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []);
314 pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []);
313 pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']);
315 pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']);
314 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
316 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
315 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
317 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
316 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
318 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
317 pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []);
319 pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []);
318 pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []);
320 pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []);
319 pyroutes.register('notifications_show_all', '/_admin/notifications', []);
321 pyroutes.register('notifications_show_all', '/_admin/notifications', []);
320 pyroutes.register('notifications_mark_all_read', '/_admin/notifications/mark_all_read', []);
322 pyroutes.register('notifications_mark_all_read', '/_admin/notifications/mark_all_read', []);
321 pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']);
323 pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']);
322 pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']);
324 pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']);
323 pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']);
325 pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']);
324 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
326 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
325 pyroutes.register('gists_show', '/_admin/gists', []);
327 pyroutes.register('gists_show', '/_admin/gists', []);
326 pyroutes.register('gists_new', '/_admin/gists/new', []);
328 pyroutes.register('gists_new', '/_admin/gists/new', []);
327 pyroutes.register('gists_create', '/_admin/gists/create', []);
329 pyroutes.register('gists_create', '/_admin/gists/create', []);
328 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
330 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
329 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
331 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
330 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
332 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
331 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
333 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
332 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
334 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
333 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/%(revision)s', ['gist_id', 'revision']);
335 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/%(revision)s', ['gist_id', 'revision']);
334 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
336 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
335 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
337 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
336 pyroutes.register('debug_style_home', '/_admin/debug_style', []);
338 pyroutes.register('debug_style_home', '/_admin/debug_style', []);
337 pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']);
339 pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']);
338 pyroutes.register('apiv2', '/_admin/api', []);
340 pyroutes.register('apiv2', '/_admin/api', []);
339 pyroutes.register('admin_settings_license', '/_admin/settings/license', []);
341 pyroutes.register('admin_settings_license', '/_admin/settings/license', []);
340 pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []);
342 pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []);
341 pyroutes.register('login', '/_admin/login', []);
343 pyroutes.register('login', '/_admin/login', []);
342 pyroutes.register('register', '/_admin/register', []);
344 pyroutes.register('register', '/_admin/register', []);
343 pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']);
345 pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']);
344 pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']);
346 pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']);
345 pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']);
347 pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']);
346 pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']);
348 pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']);
347 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
349 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
348 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
350 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
349 pyroutes.register('admin_settings_scheduler_show_tasks', '/_admin/settings/scheduler/_tasks', []);
351 pyroutes.register('admin_settings_scheduler_show_tasks', '/_admin/settings/scheduler/_tasks', []);
350 pyroutes.register('admin_settings_scheduler_show_all', '/_admin/settings/scheduler', []);
352 pyroutes.register('admin_settings_scheduler_show_all', '/_admin/settings/scheduler', []);
351 pyroutes.register('admin_settings_scheduler_new', '/_admin/settings/scheduler/new', []);
353 pyroutes.register('admin_settings_scheduler_new', '/_admin/settings/scheduler/new', []);
352 pyroutes.register('admin_settings_scheduler_create', '/_admin/settings/scheduler/create', []);
354 pyroutes.register('admin_settings_scheduler_create', '/_admin/settings/scheduler/create', []);
353 pyroutes.register('admin_settings_scheduler_edit', '/_admin/settings/scheduler/%(schedule_id)s', ['schedule_id']);
355 pyroutes.register('admin_settings_scheduler_edit', '/_admin/settings/scheduler/%(schedule_id)s', ['schedule_id']);
354 pyroutes.register('admin_settings_scheduler_update', '/_admin/settings/scheduler/%(schedule_id)s/update', ['schedule_id']);
356 pyroutes.register('admin_settings_scheduler_update', '/_admin/settings/scheduler/%(schedule_id)s/update', ['schedule_id']);
355 pyroutes.register('admin_settings_scheduler_delete', '/_admin/settings/scheduler/%(schedule_id)s/delete', ['schedule_id']);
357 pyroutes.register('admin_settings_scheduler_delete', '/_admin/settings/scheduler/%(schedule_id)s/delete', ['schedule_id']);
356 pyroutes.register('admin_settings_scheduler_execute', '/_admin/settings/scheduler/%(schedule_id)s/execute', ['schedule_id']);
358 pyroutes.register('admin_settings_scheduler_execute', '/_admin/settings/scheduler/%(schedule_id)s/execute', ['schedule_id']);
357 pyroutes.register('admin_settings_automation', '/_admin/settings/automation', []);
359 pyroutes.register('admin_settings_automation', '/_admin/settings/automation', []);
358 pyroutes.register('admin_settings_automation_update', '/_admin/settings/automation/%(entry_id)s/update', ['entry_id']);
360 pyroutes.register('admin_settings_automation_update', '/_admin/settings/automation/%(entry_id)s/update', ['entry_id']);
359 pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []);
361 pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []);
360 pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []);
362 pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []);
361 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
363 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
362 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
364 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
363 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
365 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
364 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
366 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
365 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
367 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
366 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
368 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
367 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
369 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
368 pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']);
370 pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']);
369 pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']);
371 pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']);
370 pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']);
372 pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']);
371 pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']);
373 pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']);
372 pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']);
374 pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']);
373 pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']);
375 pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']);
374 pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']);
376 pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']);
375 pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']);
377 pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']);
376 }
378 }
@@ -1,974 +1,974 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="root.mako"/>
2 <%inherit file="root.mako"/>
3
3
4 <%include file="/ejs_templates/templates.html"/>
4 <%include file="/ejs_templates/templates.html"/>
5
5
6 <div class="outerwrapper">
6 <div class="outerwrapper">
7 <!-- HEADER -->
7 <!-- HEADER -->
8 <div class="header">
8 <div class="header">
9 <div id="header-inner" class="wrapper">
9 <div id="header-inner" class="wrapper">
10 <div id="logo">
10 <div id="logo">
11 <div class="logo-wrapper">
11 <div class="logo-wrapper">
12 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
12 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
13 </div>
13 </div>
14 % if c.rhodecode_name:
14 % if c.rhodecode_name:
15 <div class="branding">
15 <div class="branding">
16 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
16 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
17 </div>
17 </div>
18 % endif
18 % endif
19 </div>
19 </div>
20 <!-- MENU BAR NAV -->
20 <!-- MENU BAR NAV -->
21 ${self.menu_bar_nav()}
21 ${self.menu_bar_nav()}
22 <!-- END MENU BAR NAV -->
22 <!-- END MENU BAR NAV -->
23 </div>
23 </div>
24 </div>
24 </div>
25 ${self.menu_bar_subnav()}
25 ${self.menu_bar_subnav()}
26 <!-- END HEADER -->
26 <!-- END HEADER -->
27
27
28 <!-- CONTENT -->
28 <!-- CONTENT -->
29 <div id="content" class="wrapper">
29 <div id="content" class="wrapper">
30
30
31 <rhodecode-toast id="notifications"></rhodecode-toast>
31 <rhodecode-toast id="notifications"></rhodecode-toast>
32
32
33 <div class="main">
33 <div class="main">
34 ${next.main()}
34 ${next.main()}
35 </div>
35 </div>
36 </div>
36 </div>
37 <!-- END CONTENT -->
37 <!-- END CONTENT -->
38
38
39 </div>
39 </div>
40 <!-- FOOTER -->
40 <!-- FOOTER -->
41 <div id="footer">
41 <div id="footer">
42 <div id="footer-inner" class="title wrapper">
42 <div id="footer-inner" class="title wrapper">
43 <div>
43 <div>
44 <p class="footer-link-right">
44 <p class="footer-link-right">
45 % if c.visual.show_version:
45 % if c.visual.show_version:
46 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
46 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
47 % endif
47 % endif
48 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
48 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
49 % if c.visual.rhodecode_support_url:
49 % if c.visual.rhodecode_support_url:
50 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
50 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
51 % endif
51 % endif
52 </p>
52 </p>
53 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
53 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
54 <p class="server-instance" style="display:${sid}">
54 <p class="server-instance" style="display:${sid}">
55 ## display hidden instance ID if specially defined
55 ## display hidden instance ID if specially defined
56 % if c.rhodecode_instanceid:
56 % if c.rhodecode_instanceid:
57 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
57 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
58 % endif
58 % endif
59 </p>
59 </p>
60 </div>
60 </div>
61 </div>
61 </div>
62 </div>
62 </div>
63
63
64 <!-- END FOOTER -->
64 <!-- END FOOTER -->
65
65
66 ### MAKO DEFS ###
66 ### MAKO DEFS ###
67
67
68 <%def name="menu_bar_subnav()">
68 <%def name="menu_bar_subnav()">
69 </%def>
69 </%def>
70
70
71 <%def name="breadcrumbs(class_='breadcrumbs')">
71 <%def name="breadcrumbs(class_='breadcrumbs')">
72 <div class="${class_}">
72 <div class="${class_}">
73 ${self.breadcrumbs_links()}
73 ${self.breadcrumbs_links()}
74 </div>
74 </div>
75 </%def>
75 </%def>
76
76
77 <%def name="admin_menu(active=None)">
77 <%def name="admin_menu(active=None)">
78 <%
78 <%
79 def is_active(selected):
79 def is_active(selected):
80 if selected == active:
80 if selected == active:
81 return "active"
81 return "active"
82 %>
82 %>
83
83
84 <div id="context-bar">
84 <div id="context-bar">
85 <div class="wrapper">
85 <div class="wrapper">
86 <div class="title">
86 <div class="title">
87 <div class="title-content">
87 <div class="title-content">
88 <div class="title-main">
88 <div class="title-main">
89 % if c.is_super_admin:
89 % if c.is_super_admin:
90 ${_('Super Admin Panel')}
90 ${_('Super Admin Panel')}
91 % else:
91 % else:
92 ${_('Delegated Admin Panel')}
92 ${_('Delegated Admin Panel')}
93 % endif
93 % endif
94 </div>
94 </div>
95 </div>
95 </div>
96 </div>
96 </div>
97
97
98 <ul id="context-pages" class="navigation horizontal-list">
98 <ul id="context-pages" class="navigation horizontal-list">
99
99
100 ## super admin case
100 ## super admin case
101 % if c.is_super_admin:
101 % if c.is_super_admin:
102 <li class="${is_active('audit_logs')}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
102 <li class="${is_active('audit_logs')}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
103 <li class="${is_active('repositories')}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
103 <li class="${is_active('repositories')}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
104 <li class="${is_active('repository_groups')}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
104 <li class="${is_active('repository_groups')}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
105 <li class="${is_active('users')}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
105 <li class="${is_active('users')}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
106 <li class="${is_active('user_groups')}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
106 <li class="${is_active('user_groups')}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
107 <li class="${is_active('permissions')}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
107 <li class="${is_active('permissions')}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
108 <li class="${is_active('authentication')}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
108 <li class="${is_active('authentication')}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
109 <li class="${is_active('integrations')}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
109 <li class="${is_active('integrations')}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
110 <li class="${is_active('defaults')}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
110 <li class="${is_active('defaults')}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
111 <li class="${is_active('settings')}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
111 <li class="${is_active('settings')}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
112
112
113 ## delegated admin
113 ## delegated admin
114 % elif c.is_delegated_admin:
114 % elif c.is_delegated_admin:
115 <%
115 <%
116 repositories=c.auth_user.repositories_admin or c.can_create_repo
116 repositories=c.auth_user.repositories_admin or c.can_create_repo
117 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
117 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
118 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
118 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
119 %>
119 %>
120
120
121 %if repositories:
121 %if repositories:
122 <li class="${is_active('repositories')} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
122 <li class="${is_active('repositories')} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
123 %endif
123 %endif
124 %if repository_groups:
124 %if repository_groups:
125 <li class="${is_active('repository_groups')} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
125 <li class="${is_active('repository_groups')} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
126 %endif
126 %endif
127 %if user_groups:
127 %if user_groups:
128 <li class="${is_active('user_groups')} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
128 <li class="${is_active('user_groups')} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
129 %endif
129 %endif
130 % endif
130 % endif
131 </ul>
131 </ul>
132
132
133 </div>
133 </div>
134 <div class="clear"></div>
134 <div class="clear"></div>
135 </div>
135 </div>
136 </%def>
136 </%def>
137
137
138 <%def name="dt_info_panel(elements)">
138 <%def name="dt_info_panel(elements)">
139 <dl class="dl-horizontal">
139 <dl class="dl-horizontal">
140 %for dt, dd, title, show_items in elements:
140 %for dt, dd, title, show_items in elements:
141 <dt>${dt}:</dt>
141 <dt>${dt}:</dt>
142 <dd title="${h.tooltip(title)}">
142 <dd title="${h.tooltip(title)}">
143 %if callable(dd):
143 %if callable(dd):
144 ## allow lazy evaluation of elements
144 ## allow lazy evaluation of elements
145 ${dd()}
145 ${dd()}
146 %else:
146 %else:
147 ${dd}
147 ${dd}
148 %endif
148 %endif
149 %if show_items:
149 %if show_items:
150 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
150 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
151 %endif
151 %endif
152 </dd>
152 </dd>
153
153
154 %if show_items:
154 %if show_items:
155 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
155 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
156 %for item in show_items:
156 %for item in show_items:
157 <dt></dt>
157 <dt></dt>
158 <dd>${item}</dd>
158 <dd>${item}</dd>
159 %endfor
159 %endfor
160 </div>
160 </div>
161 %endif
161 %endif
162
162
163 %endfor
163 %endfor
164 </dl>
164 </dl>
165 </%def>
165 </%def>
166
166
167 <%def name="gravatar(email, size=16)">
167 <%def name="gravatar(email, size=16)">
168 <%
168 <%
169 if (size > 16):
169 if (size > 16):
170 gravatar_class = 'gravatar gravatar-large'
170 gravatar_class = 'gravatar gravatar-large'
171 else:
171 else:
172 gravatar_class = 'gravatar'
172 gravatar_class = 'gravatar'
173 %>
173 %>
174 <%doc>
174 <%doc>
175 TODO: johbo: For now we serve double size images to make it smooth
175 TODO: johbo: For now we serve double size images to make it smooth
176 for retina. This is how it worked until now. Should be replaced
176 for retina. This is how it worked until now. Should be replaced
177 with a better solution at some point.
177 with a better solution at some point.
178 </%doc>
178 </%doc>
179 <img class="${gravatar_class}" src="${h.gravatar_url(email, size * 2)}" height="${size}" width="${size}">
179 <img class="${gravatar_class}" src="${h.gravatar_url(email, size * 2)}" height="${size}" width="${size}">
180 </%def>
180 </%def>
181
181
182
182
183 <%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
183 <%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
184 <% email = h.email_or_none(contact) %>
184 <% email = h.email_or_none(contact) %>
185 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
185 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
186 ${self.gravatar(email, size)}
186 ${self.gravatar(email, size)}
187 <span class="${'user user-disabled' if show_disabled else 'user'}"> ${h.link_to_user(contact)}</span>
187 <span class="${'user user-disabled' if show_disabled else 'user'}"> ${h.link_to_user(contact)}</span>
188 </div>
188 </div>
189 </%def>
189 </%def>
190
190
191
191
192 <%def name="repo_page_title(repo_instance)">
192 <%def name="repo_page_title(repo_instance)">
193 <div class="title-content repo-title">
193 <div class="title-content repo-title">
194
194
195 <div class="title-main">
195 <div class="title-main">
196 ## SVN/HG/GIT icons
196 ## SVN/HG/GIT icons
197 %if h.is_hg(repo_instance):
197 %if h.is_hg(repo_instance):
198 <i class="icon-hg"></i>
198 <i class="icon-hg"></i>
199 %endif
199 %endif
200 %if h.is_git(repo_instance):
200 %if h.is_git(repo_instance):
201 <i class="icon-git"></i>
201 <i class="icon-git"></i>
202 %endif
202 %endif
203 %if h.is_svn(repo_instance):
203 %if h.is_svn(repo_instance):
204 <i class="icon-svn"></i>
204 <i class="icon-svn"></i>
205 %endif
205 %endif
206
206
207 ## public/private
207 ## public/private
208 %if repo_instance.private:
208 %if repo_instance.private:
209 <i class="icon-repo-private"></i>
209 <i class="icon-repo-private"></i>
210 %else:
210 %else:
211 <i class="icon-repo-public"></i>
211 <i class="icon-repo-public"></i>
212 %endif
212 %endif
213
213
214 ## repo name with group name
214 ## repo name with group name
215 ${h.breadcrumb_repo_link(repo_instance)}
215 ${h.breadcrumb_repo_link(repo_instance)}
216
216
217 ## Context Actions
217 ## Context Actions
218 <div class="pull-right">
218 <div class="pull-right">
219 %if c.rhodecode_user.username != h.DEFAULT_USER:
219 %if c.rhodecode_user.username != h.DEFAULT_USER:
220 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
220 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
221
221
222 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
222 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
223 % if c.repository_is_user_following:
223 % if c.repository_is_user_following:
224 <i class="icon-eye-off"></i>${_('Unwatch')}
224 <i class="icon-eye-off"></i>${_('Unwatch')}
225 % else:
225 % else:
226 <i class="icon-eye"></i>${_('Watch')}
226 <i class="icon-eye"></i>${_('Watch')}
227 % endif
227 % endif
228
228
229 </a>
229 </a>
230 %else:
230 %else:
231 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
231 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
232 %endif
232 %endif
233 </div>
233 </div>
234
234
235 </div>
235 </div>
236
236
237 ## FORKED
237 ## FORKED
238 %if repo_instance.fork:
238 %if repo_instance.fork:
239 <p class="discreet">
239 <p class="discreet">
240 <i class="icon-code-fork"></i> ${_('Fork of')}
240 <i class="icon-code-fork"></i> ${_('Fork of')}
241 ${h.link_to_if(c.has_origin_repo_read_perm,repo_instance.fork.repo_name, h.route_path('repo_summary', repo_name=repo_instance.fork.repo_name))}
241 ${h.link_to_if(c.has_origin_repo_read_perm,repo_instance.fork.repo_name, h.route_path('repo_summary', repo_name=repo_instance.fork.repo_name))}
242 </p>
242 </p>
243 %endif
243 %endif
244
244
245 ## IMPORTED FROM REMOTE
245 ## IMPORTED FROM REMOTE
246 %if repo_instance.clone_uri:
246 %if repo_instance.clone_uri:
247 <p class="discreet">
247 <p class="discreet">
248 <i class="icon-code-fork"></i> ${_('Clone from')}
248 <i class="icon-code-fork"></i> ${_('Clone from')}
249 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
249 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
250 </p>
250 </p>
251 %endif
251 %endif
252
252
253 ## LOCKING STATUS
253 ## LOCKING STATUS
254 %if repo_instance.locked[0]:
254 %if repo_instance.locked[0]:
255 <p class="locking_locked discreet">
255 <p class="locking_locked discreet">
256 <i class="icon-repo-lock"></i>
256 <i class="icon-repo-lock"></i>
257 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
257 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
258 </p>
258 </p>
259 %elif repo_instance.enable_locking:
259 %elif repo_instance.enable_locking:
260 <p class="locking_unlocked discreet">
260 <p class="locking_unlocked discreet">
261 <i class="icon-repo-unlock"></i>
261 <i class="icon-repo-unlock"></i>
262 ${_('Repository not locked. Pull repository to lock it.')}
262 ${_('Repository not locked. Pull repository to lock it.')}
263 </p>
263 </p>
264 %endif
264 %endif
265
265
266 </div>
266 </div>
267 </%def>
267 </%def>
268
268
269 <%def name="repo_menu(active=None)">
269 <%def name="repo_menu(active=None)">
270 <%
270 <%
271 def is_active(selected):
271 def is_active(selected):
272 if selected == active:
272 if selected == active:
273 return "active"
273 return "active"
274 %>
274 %>
275 % if c.rhodecode_db_repo.archived:
275 % if c.rhodecode_db_repo.archived:
276 <div class="alert alert-warning text-center">
276 <div class="alert alert-warning text-center">
277 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
277 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
278 </div>
278 </div>
279 % endif
279 % endif
280
280
281 <!--- REPO CONTEXT BAR -->
281 <!--- REPO CONTEXT BAR -->
282 <div id="context-bar">
282 <div id="context-bar">
283 <div class="wrapper">
283 <div class="wrapper">
284
284
285 <div class="title">
285 <div class="title">
286 ${self.repo_page_title(c.rhodecode_db_repo)}
286 ${self.repo_page_title(c.rhodecode_db_repo)}
287 </div>
287 </div>
288
288
289 <ul id="context-pages" class="navigation horizontal-list">
289 <ul id="context-pages" class="navigation horizontal-list">
290 <li class="${is_active('summary')}"><a class="menulink" href="${h.route_path('repo_summary', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
290 <li class="${is_active('summary')}"><a class="menulink" href="${h.route_path('repo_summary', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
291 <li class="${is_active('commits')}"><a class="menulink" href="${h.route_path('repo_commits', repo_name=c.repo_name)}"><div class="menulabel">${_('Commits')}</div></a></li>
291 <li class="${is_active('commits')}"><a class="menulink" href="${h.route_path('repo_commits', repo_name=c.repo_name)}"><div class="menulabel">${_('Commits')}</div></a></li>
292 <li class="${is_active('files')}"><a class="menulink" href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.rhodecode_db_repo.landing_rev[1], f_path='')}"><div class="menulabel">${_('Files')}</div></a></li>
292 <li class="${is_active('files')}"><a class="menulink" href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.rhodecode_db_repo.landing_rev[1], f_path='')}"><div class="menulabel">${_('Files')}</div></a></li>
293 <li class="${is_active('compare')}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
293 <li class="${is_active('compare')}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
294
294
295 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
295 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
296 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
296 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
297 <li class="${is_active('showpullrequest')}">
297 <li class="${is_active('showpullrequest')}">
298 <a class="menulink" href="${h.route_path('pullrequest_show_all', repo_name=c.repo_name)}" title="${h.tooltip(_('Show Pull Requests for %s') % c.repo_name)}">
298 <a class="menulink" href="${h.route_path('pullrequest_show_all', repo_name=c.repo_name)}" title="${h.tooltip(_('Show Pull Requests for %s') % c.repo_name)}">
299 <div class="menulabel">
299 <div class="menulabel">
300 %if c.repository_pull_requests == 1:
300 %if c.repository_pull_requests == 1:
301 ${_('Pull Request')} ${c.repository_pull_requests}
301 ${_('Pull Request')} ${c.repository_pull_requests}
302 %else:
302 %else:
303 ${_('Pull Requests')} ${c.repository_pull_requests}
303 ${_('Pull Requests')} ${c.repository_pull_requests}
304 %endif
304 %endif
305 </div>
305 </div>
306 </a>
306 </a>
307 </li>
307 </li>
308 %endif
308 %endif
309
309
310 <li class="${is_active('artifacts')}"><a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}"><div class="menulabel">${_('Artifacts')} (BETA)</div></a></li>
310 <li class="${is_active('artifacts')}"><a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}"><div class="menulabel">${_('Artifacts')} (BETA)</div></a></li>
311
311
312 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
312 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
313 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Repository Settings')}</div></a></li>
313 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Repository Settings')}</div></a></li>
314 %endif
314 %endif
315
315
316 ## determine if we have "any" option available
316 ## determine if we have "any" option available
317 <%
317 <%
318 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
318 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
319 has_actions = (c.rhodecode_user.username != h.DEFAULT_USER and c.rhodecode_db_repo.repo_type in ['git','hg'] ) or can_lock
319 has_actions = (c.rhodecode_user.username != h.DEFAULT_USER and c.rhodecode_db_repo.repo_type in ['git','hg'] ) or can_lock
320 %>
320 %>
321 <li class="${is_active('options')}">
321 <li class="${is_active('options')}">
322 % if has_actions:
322 % if has_actions:
323 <a class="menulink dropdown">
323 <a class="menulink dropdown">
324 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
324 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
325 </a>
325 </a>
326 <ul class="submenu">
326 <ul class="submenu">
327 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork this repository')}</a></li>
327 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork this repository')}</a></li>
328 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
328 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
329 %if can_lock:
329 %if can_lock:
330 %if c.rhodecode_db_repo.locked[0]:
330 %if c.rhodecode_db_repo.locked[0]:
331 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
331 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
332 %else:
332 %else:
333 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
333 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
334 %endif
334 %endif
335 %endif
335 %endif
336 </ul>
336 </ul>
337 % else:
337 % else:
338 <a class="menulink disabled">
338 <a class="menulink disabled">
339 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
339 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
340 </a>
340 </a>
341 % endif
341 % endif
342 </li>
342 </li>
343
343
344 </ul>
344 </ul>
345 </div>
345 </div>
346 <div class="clear"></div>
346 <div class="clear"></div>
347 </div>
347 </div>
348
348
349 <!--- REPO END CONTEXT BAR -->
349 <!--- REPO END CONTEXT BAR -->
350
350
351 </%def>
351 </%def>
352
352
353 <%def name="repo_group_page_title(repo_group_instance)">
353 <%def name="repo_group_page_title(repo_group_instance)">
354 <div class="title-content">
354 <div class="title-content">
355 <div class="title-main">
355 <div class="title-main">
356 ## Repository Group icon
356 ## Repository Group icon
357 <i class="icon-repo-group"></i>
357 <i class="icon-repo-group"></i>
358
358
359 ## repo name with group name
359 ## repo name with group name
360 ${h.breadcrumb_repo_group_link(repo_group_instance)}
360 ${h.breadcrumb_repo_group_link(repo_group_instance)}
361 </div>
361 </div>
362
362
363 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
363 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
364 <div class="repo-group-desc discreet">
364 <div class="repo-group-desc discreet">
365 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
365 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
366 </div>
366 </div>
367
367
368 </div>
368 </div>
369 </%def>
369 </%def>
370
370
371 <%def name="repo_group_menu(active=None)">
371 <%def name="repo_group_menu(active=None)">
372 <%
372 <%
373 def is_active(selected):
373 def is_active(selected):
374 if selected == active:
374 if selected == active:
375 return "active"
375 return "active"
376
376
377 gr_name = c.repo_group.group_name if c.repo_group else None
377 gr_name = c.repo_group.group_name if c.repo_group else None
378 # create repositories with write permission on group is set to true
378 # create repositories with write permission on group is set to true
379 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
379 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
380 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
380 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
381 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
381 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
382
382
383 %>
383 %>
384
384
385 <!--- REPO GROUP CONTEXT BAR -->
385 <!--- REPO GROUP CONTEXT BAR -->
386 <div id="context-bar">
386 <div id="context-bar">
387 <div class="wrapper">
387 <div class="wrapper">
388 <div class="title">
388 <div class="title">
389 ${self.repo_group_page_title(c.repo_group)}
389 ${self.repo_group_page_title(c.repo_group)}
390 </div>
390 </div>
391
391
392 <ul id="context-pages" class="navigation horizontal-list">
392 <ul id="context-pages" class="navigation horizontal-list">
393 <li class="${is_active('home')}"><a class="menulink" href="${h.route_path('repo_group_home', repo_group_name=c.repo_group.group_name)}"><div class="menulabel">${_('Group Home')}</div></a></li>
393 <li class="${is_active('home')}"><a class="menulink" href="${h.route_path('repo_group_home', repo_group_name=c.repo_group.group_name)}"><div class="menulabel">${_('Group Home')}</div></a></li>
394 % if c.is_super_admin or group_admin:
394 % if c.is_super_admin or group_admin:
395 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo_group',repo_group_name=c.repo_group.group_name)}" title="${_('You have admin right to this group, and can edit it')}"><div class="menulabel">${_('Group Settings')}</div></a></li>
395 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo_group',repo_group_name=c.repo_group.group_name)}" title="${_('You have admin right to this group, and can edit it')}"><div class="menulabel">${_('Group Settings')}</div></a></li>
396 % endif
396 % endif
397 ## determine if we have "any" option available
397 ## determine if we have "any" option available
398 <%
398 <%
399 can_create_repos = c.is_super_admin or group_admin or (group_write and create_on_write)
399 can_create_repos = c.is_super_admin or group_admin or (group_write and create_on_write)
400 can_create_repo_groups = c.is_super_admin or group_admin
400 can_create_repo_groups = c.is_super_admin or group_admin
401 has_actions = can_create_repos or can_create_repo_groups
401 has_actions = can_create_repos or can_create_repo_groups
402 %>
402 %>
403 <li class="${is_active('options')}">
403 <li class="${is_active('options')}">
404 % if has_actions:
404 % if has_actions:
405 <a class="menulink dropdown">
405 <a class="menulink dropdown">
406 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
406 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
407 </a>
407 </a>
408 <ul class="submenu">
408 <ul class="submenu">
409 %if can_create_repos:
409 %if can_create_repos:
410 <li><a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('Add Repository')}</a></li>
410 <li><a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('Add Repository')}</a></li>
411 %endif
411 %endif
412 %if can_create_repo_groups:
412 %if can_create_repo_groups:
413 <li><a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'Add Repository Group')}</a></li>
413 <li><a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'Add Repository Group')}</a></li>
414 %endif
414 %endif
415 </ul>
415 </ul>
416 % else:
416 % else:
417 <a class="menulink disabled">
417 <a class="menulink disabled">
418 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
418 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
419 </a>
419 </a>
420 % endif
420 % endif
421 </li>
421 </li>
422 </ul>
422 </ul>
423 </div>
423 </div>
424 <div class="clear"></div>
424 <div class="clear"></div>
425 </div>
425 </div>
426
426
427 <!--- REPO GROUP CONTEXT BAR -->
427 <!--- REPO GROUP CONTEXT BAR -->
428
428
429 </%def>
429 </%def>
430
430
431
431
432 <%def name="usermenu(active=False)">
432 <%def name="usermenu(active=False)">
433 ## USER MENU
433 ## USER MENU
434 <li id="quick_login_li" class="${'active' if active else ''}">
434 <li id="quick_login_li" class="${'active' if active else ''}">
435 % if c.rhodecode_user.username == h.DEFAULT_USER:
435 % if c.rhodecode_user.username == h.DEFAULT_USER:
436 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
436 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
437 ${gravatar(c.rhodecode_user.email, 20)}
437 ${gravatar(c.rhodecode_user.email, 20)}
438 <span class="user">
438 <span class="user">
439 <span>${_('Sign in')}</span>
439 <span>${_('Sign in')}</span>
440 </span>
440 </span>
441 </a>
441 </a>
442 % else:
442 % else:
443 ## logged in user
443 ## logged in user
444 <a id="quick_login_link" class="menulink childs">
444 <a id="quick_login_link" class="menulink childs">
445 ${gravatar(c.rhodecode_user.email, 20)}
445 ${gravatar(c.rhodecode_user.email, 20)}
446 <span class="user">
446 <span class="user">
447 <span class="menu_link_user">${c.rhodecode_user.username}</span>
447 <span class="menu_link_user">${c.rhodecode_user.username}</span>
448 <div class="show_more"></div>
448 <div class="show_more"></div>
449 </span>
449 </span>
450 </a>
450 </a>
451 ## subnav with menu for logged in user
451 ## subnav with menu for logged in user
452 <div class="user-menu submenu">
452 <div class="user-menu submenu">
453 <div id="quick_login">
453 <div id="quick_login">
454 %if c.rhodecode_user.username != h.DEFAULT_USER:
454 %if c.rhodecode_user.username != h.DEFAULT_USER:
455 <div class="">
455 <div class="">
456 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
456 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
457 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
457 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
458 <div class="email">${c.rhodecode_user.email}</div>
458 <div class="email">${c.rhodecode_user.email}</div>
459 </div>
459 </div>
460 <div class="">
460 <div class="">
461 <ol class="links">
461 <ol class="links">
462 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
462 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
463 % if c.rhodecode_user.personal_repo_group:
463 % if c.rhodecode_user.personal_repo_group:
464 <li>${h.link_to(_(u'My personal group'), h.route_path('repo_group_home', repo_group_name=c.rhodecode_user.personal_repo_group.group_name))}</li>
464 <li>${h.link_to(_(u'My personal group'), h.route_path('repo_group_home', repo_group_name=c.rhodecode_user.personal_repo_group.group_name))}</li>
465 % endif
465 % endif
466 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
466 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
467 ## bookmark-items
467 ## bookmark-items
468 <li class="bookmark-items">
468 <li class="bookmark-items">
469 ${_('Bookmarks')}
469 ${_('Bookmarks')}
470 <div class="pull-right">
470 <div class="pull-right">
471 <a href="${h.route_path('my_account_bookmarks')}">${_('Manage')}</a>
471 <a href="${h.route_path('my_account_bookmarks')}">${_('Manage')}</a>
472 </div>
472 </div>
473 </li>
473 </li>
474 % if not c.bookmark_items:
474 % if not c.bookmark_items:
475 <li>
475 <li>
476 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
476 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
477 </li>
477 </li>
478 % endif
478 % endif
479 % for item in c.bookmark_items:
479 % for item in c.bookmark_items:
480 <li>
480 <li>
481 % if item.repository:
481 % if item.repository:
482 <div>
482 <div>
483 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
483 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
484 <code>${item.position}</code>
484 <code>${item.position}</code>
485 % if item.repository.repo_type == 'hg':
485 % if item.repository.repo_type == 'hg':
486 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
486 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
487 % elif item.repository.repo_type == 'git':
487 % elif item.repository.repo_type == 'git':
488 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
488 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
489 % elif item.repository.repo_type == 'svn':
489 % elif item.repository.repo_type == 'svn':
490 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
490 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
491 % endif
491 % endif
492 ${(item.title or h.shorter(item.repository.repo_name, 30))}
492 ${(item.title or h.shorter(item.repository.repo_name, 30))}
493 </a>
493 </a>
494 </div>
494 </div>
495 % elif item.repository_group:
495 % elif item.repository_group:
496 <div>
496 <div>
497 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
497 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
498 <code>${item.position}</code>
498 <code>${item.position}</code>
499 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
499 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
500 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
500 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
501 </a>
501 </a>
502 </div>
502 </div>
503 % else:
503 % else:
504 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
504 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
505 <code>${item.position}</code>
505 <code>${item.position}</code>
506 ${item.title}
506 ${item.title}
507 </a>
507 </a>
508 % endif
508 % endif
509 </li>
509 </li>
510 % endfor
510 % endfor
511
511
512 <li class="logout">
512 <li class="logout">
513 ${h.secure_form(h.route_path('logout'), request=request)}
513 ${h.secure_form(h.route_path('logout'), request=request)}
514 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
514 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
515 ${h.end_form()}
515 ${h.end_form()}
516 </li>
516 </li>
517 </ol>
517 </ol>
518 </div>
518 </div>
519 %endif
519 %endif
520 </div>
520 </div>
521 </div>
521 </div>
522 ## unread counter
522 ## unread counter
523 <div class="pill_container">
523 <div class="pill_container">
524 <a class="menu_link_notifications ${'empty' if c.unread_notifications == 0 else ''}" href="${h.route_path('notifications_show_all')}">${c.unread_notifications}</a>
524 <a class="menu_link_notifications ${'empty' if c.unread_notifications == 0 else ''}" href="${h.route_path('notifications_show_all')}">${c.unread_notifications}</a>
525 </div>
525 </div>
526 % endif
526 % endif
527 </li>
527 </li>
528 </%def>
528 </%def>
529
529
530 <%def name="menu_items(active=None)">
530 <%def name="menu_items(active=None)">
531 <%
531 <%
532 def is_active(selected):
532 def is_active(selected):
533 if selected == active:
533 if selected == active:
534 return "active"
534 return "active"
535 return ""
535 return ""
536 %>
536 %>
537
537
538 <ul id="quick" class="main_nav navigation horizontal-list">
538 <ul id="quick" class="main_nav navigation horizontal-list">
539 ## notice box for important system messages
539 ## notice box for important system messages
540 <li style="display: none">
540 <li style="display: none">
541 <a class="notice-box" href="#openNotice" onclick="showNoticeBox(); return false">
541 <a class="notice-box" href="#openNotice" onclick="showNoticeBox(); return false">
542 <div class="menulabel-notice" >
542 <div class="menulabel-notice" >
543 0
543 0
544 </div>
544 </div>
545 </a>
545 </a>
546 </li>
546 </li>
547
547
548 ## Main filter
548 ## Main filter
549 <li>
549 <li>
550 <div class="menulabel main_filter_box">
550 <div class="menulabel main_filter_box">
551 <div class="main_filter_input_box">
551 <div class="main_filter_input_box">
552 <ul class="searchItems">
552 <ul class="searchItems">
553
553
554 % if c.template_context['search_context']['repo_id']:
554 % if c.template_context['search_context']['repo_id']:
555 <li class="searchTag searchTagFilter searchTagHidable" >
555 <li class="searchTag searchTagFilter searchTagHidable" >
556 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
556 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
557 <span class="tag">
557 <span class="tag">
558 This repo
558 This repo
559 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
559 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
560 </span>
560 </span>
561 ##</a>
561 ##</a>
562 </li>
562 </li>
563 % elif c.template_context['search_context']['repo_group_id']:
563 % elif c.template_context['search_context']['repo_group_id']:
564 <li class="searchTag searchTagFilter searchTagHidable">
564 <li class="searchTag searchTagFilter searchTagHidable">
565 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
565 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
566 <span class="tag">
566 <span class="tag">
567 This group
567 This group
568 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
568 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
569 </span>
569 </span>
570 ##</a>
570 ##</a>
571 </li>
571 </li>
572 % endif
572 % endif
573
573
574 <li class="searchTagInput">
574 <li class="searchTagInput">
575 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
575 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
576 </li>
576 </li>
577 <li class="searchTag searchTagHelp">
577 <li class="searchTag searchTagHelp">
578 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
578 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
579 </li>
579 </li>
580 </ul>
580 </ul>
581 </div>
581 </div>
582 </div>
582 </div>
583
583
584 <div id="main_filter_help" style="display: none">
584 <div id="main_filter_help" style="display: none">
585 - Use '/' key to quickly access this field.
585 - Use '/' key to quickly access this field.
586
586
587 - Enter a name of repository, or repository group for quick search.
587 - Enter a name of repository, or repository group for quick search.
588
588
589 - Prefix query to allow special search:
589 - Prefix query to allow special search:
590
590
591 user:admin, to search for usernames, always global
591 user:admin, to search for usernames, always global
592
592
593 user_group:devops, to search for user groups, always global
593 user_group:devops, to search for user groups, always global
594
594
595 commit:efced4, to search for commits, scoped to repositories or groups
595 commit:efced4, to search for commits, scoped to repositories or groups
596
596
597 file:models.py, to search for file paths, scoped to repositories or groups
597 file:models.py, to search for file paths, scoped to repositories or groups
598
598
599 % if c.template_context['search_context']['repo_id']:
599 % if c.template_context['search_context']['repo_id']:
600 For advanced full text search visit: <a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">repository search</a>
600 For advanced full text search visit: <a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">repository search</a>
601 % elif c.template_context['search_context']['repo_group_id']:
601 % elif c.template_context['search_context']['repo_group_id']:
602 For advanced full text search visit: <a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">repository group search</a>
602 For advanced full text search visit: <a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">repository group search</a>
603 % else:
603 % else:
604 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
604 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
605 % endif
605 % endif
606 </div>
606 </div>
607 </li>
607 </li>
608
608
609 ## ROOT MENU
609 ## ROOT MENU
610 <li class="${is_active('home')}">
610 <li class="${is_active('home')}">
611 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
611 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
612 <div class="menulabel">${_('Home')}</div>
612 <div class="menulabel">${_('Home')}</div>
613 </a>
613 </a>
614 </li>
614 </li>
615
615
616 %if c.rhodecode_user.username != h.DEFAULT_USER:
616 %if c.rhodecode_user.username != h.DEFAULT_USER:
617 <li class="${is_active('journal')}">
617 <li class="${is_active('journal')}">
618 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
618 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
619 <div class="menulabel">${_('Journal')}</div>
619 <div class="menulabel">${_('Journal')}</div>
620 </a>
620 </a>
621 </li>
621 </li>
622 %else:
622 %else:
623 <li class="${is_active('journal')}">
623 <li class="${is_active('journal')}">
624 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
624 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
625 <div class="menulabel">${_('Public journal')}</div>
625 <div class="menulabel">${_('Public journal')}</div>
626 </a>
626 </a>
627 </li>
627 </li>
628 %endif
628 %endif
629
629
630 <li class="${is_active('gists')}">
630 <li class="${is_active('gists')}">
631 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
631 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
632 <div class="menulabel">${_('Gists')}</div>
632 <div class="menulabel">${_('Gists')}</div>
633 </a>
633 </a>
634 </li>
634 </li>
635
635
636 % if c.is_super_admin or c.is_delegated_admin:
636 % if c.is_super_admin or c.is_delegated_admin:
637 <li class="${is_active('admin')}">
637 <li class="${is_active('admin')}">
638 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
638 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
639 <div class="menulabel">${_('Admin')} </div>
639 <div class="menulabel">${_('Admin')} </div>
640 </a>
640 </a>
641 </li>
641 </li>
642 % endif
642 % endif
643
643
644 ## render extra user menu
644 ## render extra user menu
645 ${usermenu(active=(active=='my_account'))}
645 ${usermenu(active=(active=='my_account'))}
646
646
647 % if c.debug_style:
647 % if c.debug_style:
648 <li>
648 <li>
649 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
649 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
650 <div class="menulabel">${_('[Style]')}</div>
650 <div class="menulabel">${_('[Style]')}</div>
651 </a>
651 </a>
652 </li>
652 </li>
653 % endif
653 % endif
654 </ul>
654 </ul>
655
655
656 <script type="text/javascript">
656 <script type="text/javascript">
657 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
657 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
658
658
659 var formatRepoResult = function(result, container, query, escapeMarkup) {
659 var formatRepoResult = function(result, container, query, escapeMarkup) {
660 return function(data, escapeMarkup) {
660 return function(data, escapeMarkup) {
661 if (!data.repo_id){
661 if (!data.repo_id){
662 return data.text; // optgroup text Repositories
662 return data.text; // optgroup text Repositories
663 }
663 }
664
664
665 var tmpl = '';
665 var tmpl = '';
666 var repoType = data['repo_type'];
666 var repoType = data['repo_type'];
667 var repoName = data['text'];
667 var repoName = data['text'];
668
668
669 if(data && data.type == 'repo'){
669 if(data && data.type == 'repo'){
670 if(repoType === 'hg'){
670 if(repoType === 'hg'){
671 tmpl += '<i class="icon-hg"></i> ';
671 tmpl += '<i class="icon-hg"></i> ';
672 }
672 }
673 else if(repoType === 'git'){
673 else if(repoType === 'git'){
674 tmpl += '<i class="icon-git"></i> ';
674 tmpl += '<i class="icon-git"></i> ';
675 }
675 }
676 else if(repoType === 'svn'){
676 else if(repoType === 'svn'){
677 tmpl += '<i class="icon-svn"></i> ';
677 tmpl += '<i class="icon-svn"></i> ';
678 }
678 }
679 if(data['private']){
679 if(data['private']){
680 tmpl += '<i class="icon-lock" ></i> ';
680 tmpl += '<i class="icon-lock" ></i> ';
681 }
681 }
682 else if(visualShowPublicIcon){
682 else if(visualShowPublicIcon){
683 tmpl += '<i class="icon-unlock-alt"></i> ';
683 tmpl += '<i class="icon-unlock-alt"></i> ';
684 }
684 }
685 }
685 }
686 tmpl += escapeMarkup(repoName);
686 tmpl += escapeMarkup(repoName);
687 return tmpl;
687 return tmpl;
688
688
689 }(result, escapeMarkup);
689 }(result, escapeMarkup);
690 };
690 };
691
691
692 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
692 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
693 return function(data, escapeMarkup) {
693 return function(data, escapeMarkup) {
694 if (!data.repo_group_id){
694 if (!data.repo_group_id){
695 return data.text; // optgroup text Repositories
695 return data.text; // optgroup text Repositories
696 }
696 }
697
697
698 var tmpl = '';
698 var tmpl = '';
699 var repoGroupName = data['text'];
699 var repoGroupName = data['text'];
700
700
701 if(data){
701 if(data){
702
702
703 tmpl += '<i class="icon-repo-group"></i> ';
703 tmpl += '<i class="icon-repo-group"></i> ';
704
704
705 }
705 }
706 tmpl += escapeMarkup(repoGroupName);
706 tmpl += escapeMarkup(repoGroupName);
707 return tmpl;
707 return tmpl;
708
708
709 }(result, escapeMarkup);
709 }(result, escapeMarkup);
710 };
710 };
711
711
712 var escapeRegExChars = function (value) {
712 var escapeRegExChars = function (value) {
713 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
713 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
714 };
714 };
715
715
716 var getRepoIcon = function(repo_type) {
716 var getRepoIcon = function(repo_type) {
717 if (repo_type === 'hg') {
717 if (repo_type === 'hg') {
718 return '<i class="icon-hg"></i> ';
718 return '<i class="icon-hg"></i> ';
719 }
719 }
720 else if (repo_type === 'git') {
720 else if (repo_type === 'git') {
721 return '<i class="icon-git"></i> ';
721 return '<i class="icon-git"></i> ';
722 }
722 }
723 else if (repo_type === 'svn') {
723 else if (repo_type === 'svn') {
724 return '<i class="icon-svn"></i> ';
724 return '<i class="icon-svn"></i> ';
725 }
725 }
726 return ''
726 return ''
727 };
727 };
728
728
729 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
729 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
730
730
731 if (value.split(':').length === 2) {
731 if (value.split(':').length === 2) {
732 value = value.split(':')[1]
732 value = value.split(':')[1]
733 }
733 }
734
734
735 var searchType = data['type'];
735 var searchType = data['type'];
736 var searchSubType = data['subtype'];
736 var searchSubType = data['subtype'];
737 var valueDisplay = data['value_display'];
737 var valueDisplay = data['value_display'];
738
738
739 var pattern = '(' + escapeRegExChars(value) + ')';
739 var pattern = '(' + escapeRegExChars(value) + ')';
740
740
741 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
741 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
742
742
743 // highlight match
743 // highlight match
744 if (searchType != 'text') {
744 if (searchType != 'text') {
745 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
745 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
746 }
746 }
747
747
748 var icon = '';
748 var icon = '';
749
749
750 if (searchType === 'hint') {
750 if (searchType === 'hint') {
751 icon += '<i class="icon-repo-group"></i> ';
751 icon += '<i class="icon-repo-group"></i> ';
752 }
752 }
753 // full text search/hints
753 // full text search/hints
754 else if (searchType === 'search') {
754 else if (searchType === 'search') {
755 icon += '<i class="icon-more"></i> ';
755 icon += '<i class="icon-more"></i> ';
756 if (searchSubType !== undefined && searchSubType == 'repo') {
756 if (searchSubType !== undefined && searchSubType == 'repo') {
757 valueDisplay += '<div class="pull-right tag">repository</div>';
757 valueDisplay += '<div class="pull-right tag">repository</div>';
758 }
758 }
759 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
759 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
760 valueDisplay += '<div class="pull-right tag">repo group</div>';
760 valueDisplay += '<div class="pull-right tag">repo group</div>';
761 }
761 }
762 }
762 }
763 // repository
763 // repository
764 else if (searchType === 'repo') {
764 else if (searchType === 'repo') {
765
765
766 var repoIcon = getRepoIcon(data['repo_type']);
766 var repoIcon = getRepoIcon(data['repo_type']);
767 icon += repoIcon;
767 icon += repoIcon;
768
768
769 if (data['private']) {
769 if (data['private']) {
770 icon += '<i class="icon-lock" ></i> ';
770 icon += '<i class="icon-lock" ></i> ';
771 }
771 }
772 else if (visualShowPublicIcon) {
772 else if (visualShowPublicIcon) {
773 icon += '<i class="icon-unlock-alt"></i> ';
773 icon += '<i class="icon-unlock-alt"></i> ';
774 }
774 }
775 }
775 }
776 // repository groups
776 // repository groups
777 else if (searchType === 'repo_group') {
777 else if (searchType === 'repo_group') {
778 icon += '<i class="icon-repo-group"></i> ';
778 icon += '<i class="icon-repo-group"></i> ';
779 }
779 }
780 // user group
780 // user group
781 else if (searchType === 'user_group') {
781 else if (searchType === 'user_group') {
782 icon += '<i class="icon-group"></i> ';
782 icon += '<i class="icon-group"></i> ';
783 }
783 }
784 // user
784 // user
785 else if (searchType === 'user') {
785 else if (searchType === 'user') {
786 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
786 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
787 }
787 }
788 // commit
788 // commit
789 else if (searchType === 'commit') {
789 else if (searchType === 'commit') {
790 var repo_data = data['repo_data'];
790 var repo_data = data['repo_data'];
791 var repoIcon = getRepoIcon(repo_data['repository_type']);
791 var repoIcon = getRepoIcon(repo_data['repository_type']);
792 if (repoIcon) {
792 if (repoIcon) {
793 icon += repoIcon;
793 icon += repoIcon;
794 } else {
794 } else {
795 icon += '<i class="icon-tag"></i>';
795 icon += '<i class="icon-tag"></i>';
796 }
796 }
797 }
797 }
798 // file
798 // file
799 else if (searchType === 'file') {
799 else if (searchType === 'file') {
800 var repo_data = data['repo_data'];
800 var repo_data = data['repo_data'];
801 var repoIcon = getRepoIcon(repo_data['repository_type']);
801 var repoIcon = getRepoIcon(repo_data['repository_type']);
802 if (repoIcon) {
802 if (repoIcon) {
803 icon += repoIcon;
803 icon += repoIcon;
804 } else {
804 } else {
805 icon += '<i class="icon-tag"></i>';
805 icon += '<i class="icon-tag"></i>';
806 }
806 }
807 }
807 }
808 // generic text
808 // generic text
809 else if (searchType === 'text') {
809 else if (searchType === 'text') {
810 icon = '';
810 icon = '';
811 }
811 }
812
812
813 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
813 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
814 return tmpl.format(icon, valueDisplay);
814 return tmpl.format(icon, valueDisplay);
815 };
815 };
816
816
817 var handleSelect = function(element, suggestion) {
817 var handleSelect = function(element, suggestion) {
818 if (suggestion.type === "hint") {
818 if (suggestion.type === "hint") {
819 // we skip action
819 // we skip action
820 $('#main_filter').focus();
820 $('#main_filter').focus();
821 }
821 }
822 else if (suggestion.type === "text") {
822 else if (suggestion.type === "text") {
823 // we skip action
823 // we skip action
824 $('#main_filter').focus();
824 $('#main_filter').focus();
825
825
826 } else {
826 } else {
827 window.location = suggestion['url'];
827 window.location = suggestion['url'];
828 }
828 }
829 };
829 };
830
830
831 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
831 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
832 if (queryLowerCase.split(':').length === 2) {
832 if (queryLowerCase.split(':').length === 2) {
833 queryLowerCase = queryLowerCase.split(':')[1]
833 queryLowerCase = queryLowerCase.split(':')[1]
834 }
834 }
835 if (suggestion.type === "text") {
835 if (suggestion.type === "text") {
836 // special case we don't want to "skip" display for
836 // special case we don't want to "skip" display for
837 return true
837 return true
838 }
838 }
839 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
839 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
840 };
840 };
841
841
842 var cleanContext = {
842 var cleanContext = {
843 repo_view_type: null,
843 repo_view_type: null,
844
844
845 repo_id: null,
845 repo_id: null,
846 repo_name: "",
846 repo_name: "",
847
847
848 repo_group_id: null,
848 repo_group_id: null,
849 repo_group_name: null
849 repo_group_name: null
850 };
850 };
851 var removeGoToFilter = function () {
851 var removeGoToFilter = function () {
852 $('.searchTagHidable').hide();
852 $('.searchTagHidable').hide();
853 $('#main_filter').autocomplete(
853 $('#main_filter').autocomplete(
854 'setOptions', {params:{search_context: cleanContext}});
854 'setOptions', {params:{search_context: cleanContext}});
855 };
855 };
856
856
857 $('#main_filter').autocomplete({
857 $('#main_filter').autocomplete({
858 serviceUrl: pyroutes.url('goto_switcher_data'),
858 serviceUrl: pyroutes.url('goto_switcher_data'),
859 params: {
859 params: {
860 "search_context": templateContext.search_context
860 "search_context": templateContext.search_context
861 },
861 },
862 minChars:2,
862 minChars:2,
863 maxHeight:400,
863 maxHeight:400,
864 deferRequestBy: 300, //miliseconds
864 deferRequestBy: 300, //miliseconds
865 tabDisabled: true,
865 tabDisabled: true,
866 autoSelectFirst: false,
866 autoSelectFirst: false,
867 containerClass: 'autocomplete-qfilter-suggestions',
867 containerClass: 'autocomplete-qfilter-suggestions',
868 formatResult: autocompleteMainFilterFormatResult,
868 formatResult: autocompleteMainFilterFormatResult,
869 lookupFilter: autocompleteMainFilterResult,
869 lookupFilter: autocompleteMainFilterResult,
870 onSelect: function (element, suggestion) {
870 onSelect: function (element, suggestion) {
871 handleSelect(element, suggestion);
871 handleSelect(element, suggestion);
872 return false;
872 return false;
873 },
873 },
874 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
874 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
875 if (jqXHR !== 'abort') {
875 if (jqXHR !== 'abort') {
876 alert("Error during search.\nError code: {0}".format(textStatus));
876 alert("Error during search.\nError code: {0}".format(textStatus));
877 window.location = '';
877 window.location = '';
878 }
878 }
879 }
879 }
880 });
880 });
881
881
882 showMainFilterBox = function () {
882 showMainFilterBox = function () {
883 $('#main_filter_help').toggle();
883 $('#main_filter_help').toggle();
884 };
884 };
885
885
886 $('#main_filter').on('keydown.autocomplete', function (e) {
886 $('#main_filter').on('keydown.autocomplete', function (e) {
887
887
888 var BACKSPACE = 8;
888 var BACKSPACE = 8;
889 var el = $(e.currentTarget);
889 var el = $(e.currentTarget);
890 if(e.which === BACKSPACE){
890 if(e.which === BACKSPACE){
891 var inputVal = el.val();
891 var inputVal = el.val();
892 if (inputVal === ""){
892 if (inputVal === ""){
893 removeGoToFilter()
893 removeGoToFilter()
894 }
894 }
895 }
895 }
896 });
896 });
897
897
898 </script>
898 </script>
899 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
899 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
900 </%def>
900 </%def>
901
901
902 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
902 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
903 <div class="modal-dialog">
903 <div class="modal-dialog">
904 <div class="modal-content">
904 <div class="modal-content">
905 <div class="modal-header">
905 <div class="modal-header">
906 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
906 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
907 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
907 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
908 </div>
908 </div>
909 <div class="modal-body">
909 <div class="modal-body">
910 <div class="block-left">
910 <div class="block-left">
911 <table class="keyboard-mappings">
911 <table class="keyboard-mappings">
912 <tbody>
912 <tbody>
913 <tr>
913 <tr>
914 <th></th>
914 <th></th>
915 <th>${_('Site-wide shortcuts')}</th>
915 <th>${_('Site-wide shortcuts')}</th>
916 </tr>
916 </tr>
917 <%
917 <%
918 elems = [
918 elems = [
919 ('/', 'Use quick search box'),
919 ('/', 'Use quick search box'),
920 ('g h', 'Goto home page'),
920 ('g h', 'Goto home page'),
921 ('g g', 'Goto my private gists page'),
921 ('g g', 'Goto my private gists page'),
922 ('g G', 'Goto my public gists page'),
922 ('g G', 'Goto my public gists page'),
923 ('g 0-9', 'Goto bookmarked items from 0-9'),
923 ('g 0-9', 'Goto bookmarked items from 0-9'),
924 ('n r', 'New repository page'),
924 ('n r', 'New repository page'),
925 ('n g', 'New gist page'),
925 ('n g', 'New gist page'),
926 ]
926 ]
927 %>
927 %>
928 %for key, desc in elems:
928 %for key, desc in elems:
929 <tr>
929 <tr>
930 <td class="keys">
930 <td class="keys">
931 <span class="key tag">${key}</span>
931 <span class="key tag">${key}</span>
932 </td>
932 </td>
933 <td>${desc}</td>
933 <td>${desc}</td>
934 </tr>
934 </tr>
935 %endfor
935 %endfor
936 </tbody>
936 </tbody>
937 </table>
937 </table>
938 </div>
938 </div>
939 <div class="block-left">
939 <div class="block-left">
940 <table class="keyboard-mappings">
940 <table class="keyboard-mappings">
941 <tbody>
941 <tbody>
942 <tr>
942 <tr>
943 <th></th>
943 <th></th>
944 <th>${_('Repositories')}</th>
944 <th>${_('Repositories')}</th>
945 </tr>
945 </tr>
946 <%
946 <%
947 elems = [
947 elems = [
948 ('g s', 'Goto summary page'),
948 ('g s', 'Goto summary page'),
949 ('g c', 'Goto changelog page'),
949 ('g c', 'Goto changelog page'),
950 ('g f', 'Goto files page'),
950 ('g f', 'Goto files page'),
951 ('g F', 'Goto files page with file search activated'),
951 ('g F', 'Goto files page with file search activated'),
952 ('g p', 'Goto pull requests page'),
952 ('g p', 'Goto pull requests page'),
953 ('g o', 'Goto repository settings'),
953 ('g o', 'Goto repository settings'),
954 ('g O', 'Goto repository permissions settings'),
954 ('g O', 'Goto repository permissions settings'),
955 ]
955 ]
956 %>
956 %>
957 %for key, desc in elems:
957 %for key, desc in elems:
958 <tr>
958 <tr>
959 <td class="keys">
959 <td class="keys">
960 <span class="key tag">${key}</span>
960 <span class="key tag">${key}</span>
961 </td>
961 </td>
962 <td>${desc}</td>
962 <td>${desc}</td>
963 </tr>
963 </tr>
964 %endfor
964 %endfor
965 </tbody>
965 </tbody>
966 </table>
966 </table>
967 </div>
967 </div>
968 </div>
968 </div>
969 <div class="modal-footer">
969 <div class="modal-footer">
970 </div>
970 </div>
971 </div><!-- /.modal-content -->
971 </div><!-- /.modal-content -->
972 </div><!-- /.modal-dialog -->
972 </div><!-- /.modal-dialog -->
973 </div><!-- /.modal -->
973 </div><!-- /.modal -->
974
974
@@ -1,28 +1,28 b''
1 <%inherit file="/base/base.mako"/>
1 <%inherit file="/base/base.mako"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ## represents page title
4 ## represents page title
5 ${_('%s Summary') % c.repo_name}
5 ${_('{} Summary').format(c.repo_name)}
6 %if c.rhodecode_name:
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}
7 &middot; ${h.branding(c.rhodecode_name)}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11
11
12 <%def name="head_extra()">
12 <%def name="head_extra()">
13 <link href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name, _query=dict(auth_token=c.rhodecode_user.feed_token))}" rel="alternate" title="${h.tooltip(_('%s ATOM feed') % c.repo_name)}" type="application/atom+xml" />
13 <link href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" rel="alternate" title="${h.tooltip(_('%s ATOM feed') % c.repo_name)}" type="application/atom+xml" />
14 <link href="${h.route_path('rss_feed_home', repo_name=c.rhodecode_db_repo.repo_name, _query=dict(auth_token=c.rhodecode_user.feed_token))}" rel="alternate" title="${h.tooltip(_('%s RSS feed') % c.repo_name)}" type="application/rss+xml" />
14 <link href="${h.route_path('rss_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" rel="alternate" title="${h.tooltip(_('%s RSS feed') % c.repo_name)}" type="application/rss+xml" />
15 </%def>
15 </%def>
16
16
17
17
18 <%def name="menu_bar_nav()">
18 <%def name="menu_bar_nav()">
19 ${self.menu_items(active='repositories')}
19 ${self.menu_items(active='repositories')}
20 </%def>
20 </%def>
21
21
22
22
23 <%def name="breadcrumbs_links()"></%def>
23 <%def name="breadcrumbs_links()"></%def>
24
24
25
25
26 <%def name="main()">
26 <%def name="main()">
27 ${next.main()}
27 ${next.main()}
28 </%def>
28 </%def>
General Comments 0
You need to be logged in to leave comments. Login now