Show More
@@ -1,105 +1,112 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | |
|
3 | 3 | # Copyright (C) 2011-2019 RhodeCode GmbH |
|
4 | 4 | # |
|
5 | 5 | # This program is free software: you can redistribute it and/or modify |
|
6 | 6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 7 | # (only), as published by the Free Software Foundation. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 16 | # |
|
17 | 17 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | 21 | import logging |
|
22 | 22 | |
|
23 | 23 | from pyramid.view import view_config |
|
24 | 24 | from pyramid.httpexceptions import HTTPFound |
|
25 | 25 | |
|
26 | 26 | from rhodecode.apps._base import RepoGroupAppView |
|
27 | 27 | from rhodecode.lib import helpers as h |
|
28 | 28 | from rhodecode.lib import audit_logger |
|
29 | 29 | from rhodecode.lib.auth import ( |
|
30 | 30 | LoginRequired, CSRFRequired, HasRepoGroupPermissionAnyDecorator) |
|
31 | 31 | from rhodecode.model.repo_group import RepoGroupModel |
|
32 | 32 | from rhodecode.model.meta import Session |
|
33 | 33 | |
|
34 | 34 | log = logging.getLogger(__name__) |
|
35 | 35 | |
|
36 | 36 | |
|
37 | 37 | class RepoGroupSettingsView(RepoGroupAppView): |
|
38 | 38 | def load_default_context(self): |
|
39 | 39 | c = self._get_local_tmpl_context() |
|
40 | 40 | |
|
41 | 41 | return c |
|
42 | 42 | |
|
43 | 43 | @LoginRequired() |
|
44 | 44 | @HasRepoGroupPermissionAnyDecorator('group.admin') |
|
45 | 45 | @view_config( |
|
46 | 46 | route_name='edit_repo_group_advanced', request_method='GET', |
|
47 | 47 | renderer='rhodecode:templates/admin/repo_groups/repo_group_edit.mako') |
|
48 | 48 | def edit_repo_group_advanced(self): |
|
49 | _ = self.request.translate | |
|
49 | 50 | c = self.load_default_context() |
|
50 | 51 | c.active = 'advanced' |
|
51 | 52 | c.repo_group = self.db_repo_group |
|
53 | ||
|
54 | # update commit cache if GET flag is present | |
|
55 | if self.request.GET.get('update_commit_cache'): | |
|
56 | self.db_repo_group.update_commit_cache() | |
|
57 | h.flash(_('updated commit cache'), category='success') | |
|
58 | ||
|
52 | 59 | return self._get_template_context(c) |
|
53 | 60 | |
|
54 | 61 | @LoginRequired() |
|
55 | 62 | @HasRepoGroupPermissionAnyDecorator('group.admin') |
|
56 | 63 | @CSRFRequired() |
|
57 | 64 | @view_config( |
|
58 | 65 | route_name='edit_repo_group_advanced_delete', request_method='POST', |
|
59 | 66 | renderer='rhodecode:templates/admin/repo_groups/repo_group_edit.mako') |
|
60 | 67 | def edit_repo_group_delete(self): |
|
61 | 68 | _ = self.request.translate |
|
62 | 69 | _ungettext = self.request.plularize |
|
63 | 70 | c = self.load_default_context() |
|
64 | 71 | c.repo_group = self.db_repo_group |
|
65 | 72 | |
|
66 | 73 | repos = c.repo_group.repositories.all() |
|
67 | 74 | if repos: |
|
68 | 75 | msg = _ungettext( |
|
69 | 76 | 'This repository group contains %(num)d repository and cannot be deleted', |
|
70 | 77 | 'This repository group contains %(num)d repositories and cannot be' |
|
71 | 78 | ' deleted', |
|
72 | 79 | len(repos)) % {'num': len(repos)} |
|
73 | 80 | h.flash(msg, category='warning') |
|
74 | 81 | raise HTTPFound( |
|
75 | 82 | h.route_path('edit_repo_group_advanced', |
|
76 | 83 | repo_group_name=self.db_repo_group_name)) |
|
77 | 84 | |
|
78 | 85 | children = c.repo_group.children.all() |
|
79 | 86 | if children: |
|
80 | 87 | msg = _ungettext( |
|
81 | 88 | 'This repository group contains %(num)d subgroup and cannot be deleted', |
|
82 | 89 | 'This repository group contains %(num)d subgroups and cannot be deleted', |
|
83 | 90 | len(children)) % {'num': len(children)} |
|
84 | 91 | h.flash(msg, category='warning') |
|
85 | 92 | raise HTTPFound( |
|
86 | 93 | h.route_path('edit_repo_group_advanced', |
|
87 | 94 | repo_group_name=self.db_repo_group_name)) |
|
88 | 95 | |
|
89 | 96 | try: |
|
90 | 97 | old_values = c.repo_group.get_api_data() |
|
91 | 98 | RepoGroupModel().delete(self.db_repo_group_name) |
|
92 | 99 | |
|
93 | 100 | audit_logger.store_web( |
|
94 | 101 | 'repo_group.delete', action_data={'old_data': old_values}, |
|
95 | 102 | user=c.rhodecode_user) |
|
96 | 103 | |
|
97 | 104 | Session().commit() |
|
98 | 105 | h.flash(_('Removed repository group `%s`') % self.db_repo_group_name, |
|
99 | 106 | category='success') |
|
100 | 107 | except Exception: |
|
101 | 108 | log.exception("Exception during deletion of repository group") |
|
102 | 109 | h.flash(_('Error occurred during deletion of repository group %s') |
|
103 | 110 | % self.db_repo_group_name, category='error') |
|
104 | 111 | |
|
105 | 112 | raise HTTPFound(h.route_path('repo_groups')) |
@@ -1,311 +1,317 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | |
|
3 | 3 | # Copyright (C) 2011-2019 RhodeCode GmbH |
|
4 | 4 | # |
|
5 | 5 | # This program is free software: you can redistribute it and/or modify |
|
6 | 6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 7 | # (only), as published by the Free Software Foundation. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 16 | # |
|
17 | 17 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | 21 | import logging |
|
22 | 22 | |
|
23 | 23 | from pyramid.view import view_config |
|
24 | 24 | from pyramid.httpexceptions import HTTPFound |
|
25 | 25 | |
|
26 | 26 | from rhodecode import events |
|
27 | 27 | from rhodecode.apps._base import RepoAppView |
|
28 | 28 | from rhodecode.lib import helpers as h |
|
29 | 29 | from rhodecode.lib import audit_logger |
|
30 | 30 | from rhodecode.lib.auth import ( |
|
31 | 31 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired, |
|
32 | 32 | HasRepoPermissionAny) |
|
33 | 33 | from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError |
|
34 | 34 | from rhodecode.lib.utils2 import safe_int |
|
35 | 35 | from rhodecode.lib.vcs import RepositoryError |
|
36 | 36 | from rhodecode.model.db import Session, UserFollowing, User, Repository |
|
37 | 37 | from rhodecode.model.permission import PermissionModel |
|
38 | 38 | from rhodecode.model.repo import RepoModel |
|
39 | 39 | from rhodecode.model.scm import ScmModel |
|
40 | 40 | |
|
41 | 41 | log = logging.getLogger(__name__) |
|
42 | 42 | |
|
43 | 43 | |
|
44 | 44 | class RepoSettingsView(RepoAppView): |
|
45 | 45 | |
|
46 | 46 | def load_default_context(self): |
|
47 | 47 | c = self._get_local_tmpl_context() |
|
48 | 48 | return c |
|
49 | 49 | |
|
50 | 50 | def _get_users_with_permissions(self): |
|
51 | 51 | user_permissions = {} |
|
52 | 52 | for perm in self.db_repo.permissions(): |
|
53 | 53 | user_permissions[perm.user_id] = perm |
|
54 | 54 | |
|
55 | 55 | return user_permissions |
|
56 | 56 | |
|
57 | 57 | @LoginRequired() |
|
58 | 58 | @HasRepoPermissionAnyDecorator('repository.admin') |
|
59 | 59 | @view_config( |
|
60 | 60 | route_name='edit_repo_advanced', request_method='GET', |
|
61 | 61 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') |
|
62 | 62 | def edit_advanced(self): |
|
63 | _ = self.request.translate | |
|
63 | 64 | c = self.load_default_context() |
|
64 | 65 | c.active = 'advanced' |
|
65 | 66 | |
|
66 | 67 | c.default_user_id = User.get_default_user().user_id |
|
67 | 68 | c.in_public_journal = UserFollowing.query() \ |
|
68 | 69 | .filter(UserFollowing.user_id == c.default_user_id) \ |
|
69 | 70 | .filter(UserFollowing.follows_repository == self.db_repo).scalar() |
|
70 | 71 | |
|
71 | 72 | c.ver_info_dict = self.rhodecode_vcs_repo.get_hooks_info() |
|
72 | 73 | |
|
74 | # update commit cache if GET flag is present | |
|
75 | if self.request.GET.get('update_commit_cache'): | |
|
76 | self.db_repo.update_commit_cache() | |
|
77 | h.flash(_('updated commit cache'), category='success') | |
|
78 | ||
|
73 | 79 | return self._get_template_context(c) |
|
74 | 80 | |
|
75 | 81 | @LoginRequired() |
|
76 | 82 | @HasRepoPermissionAnyDecorator('repository.admin') |
|
77 | 83 | @CSRFRequired() |
|
78 | 84 | @view_config( |
|
79 | 85 | route_name='edit_repo_advanced_archive', request_method='POST', |
|
80 | 86 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') |
|
81 | 87 | def edit_advanced_archive(self): |
|
82 | 88 | """ |
|
83 | 89 | Archives the repository. It will become read-only, and not visible in search |
|
84 | 90 | or other queries. But still visible for super-admins. |
|
85 | 91 | """ |
|
86 | 92 | |
|
87 | 93 | _ = self.request.translate |
|
88 | 94 | |
|
89 | 95 | try: |
|
90 | 96 | old_data = self.db_repo.get_api_data() |
|
91 | 97 | RepoModel().archive(self.db_repo) |
|
92 | 98 | |
|
93 | 99 | repo = audit_logger.RepoWrap(repo_id=None, repo_name=self.db_repo.repo_name) |
|
94 | 100 | audit_logger.store_web( |
|
95 | 101 | 'repo.archive', action_data={'old_data': old_data}, |
|
96 | 102 | user=self._rhodecode_user, repo=repo) |
|
97 | 103 | |
|
98 | 104 | ScmModel().mark_for_invalidation(self.db_repo_name, delete=True) |
|
99 | 105 | h.flash( |
|
100 | 106 | _('Archived repository `%s`') % self.db_repo_name, |
|
101 | 107 | category='success') |
|
102 | 108 | Session().commit() |
|
103 | 109 | except Exception: |
|
104 | 110 | log.exception("Exception during archiving of repository") |
|
105 | 111 | h.flash(_('An error occurred during archiving of `%s`') |
|
106 | 112 | % self.db_repo_name, category='error') |
|
107 | 113 | # redirect to advanced for more deletion options |
|
108 | 114 | raise HTTPFound( |
|
109 | 115 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name, |
|
110 | 116 | _anchor='advanced-archive')) |
|
111 | 117 | |
|
112 | 118 | # flush permissions for all users defined in permissions |
|
113 | 119 | affected_user_ids = self._get_users_with_permissions().keys() |
|
114 | 120 | PermissionModel().trigger_permission_flush(affected_user_ids) |
|
115 | 121 | |
|
116 | 122 | raise HTTPFound(h.route_path('home')) |
|
117 | 123 | |
|
118 | 124 | @LoginRequired() |
|
119 | 125 | @HasRepoPermissionAnyDecorator('repository.admin') |
|
120 | 126 | @CSRFRequired() |
|
121 | 127 | @view_config( |
|
122 | 128 | route_name='edit_repo_advanced_delete', request_method='POST', |
|
123 | 129 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') |
|
124 | 130 | def edit_advanced_delete(self): |
|
125 | 131 | """ |
|
126 | 132 | Deletes the repository, or shows warnings if deletion is not possible |
|
127 | 133 | because of attached forks or other errors. |
|
128 | 134 | """ |
|
129 | 135 | _ = self.request.translate |
|
130 | 136 | handle_forks = self.request.POST.get('forks', None) |
|
131 | 137 | if handle_forks == 'detach_forks': |
|
132 | 138 | handle_forks = 'detach' |
|
133 | 139 | elif handle_forks == 'delete_forks': |
|
134 | 140 | handle_forks = 'delete' |
|
135 | 141 | |
|
136 | 142 | try: |
|
137 | 143 | old_data = self.db_repo.get_api_data() |
|
138 | 144 | RepoModel().delete(self.db_repo, forks=handle_forks) |
|
139 | 145 | |
|
140 | 146 | _forks = self.db_repo.forks.count() |
|
141 | 147 | if _forks and handle_forks: |
|
142 | 148 | if handle_forks == 'detach_forks': |
|
143 | 149 | h.flash(_('Detached %s forks') % _forks, category='success') |
|
144 | 150 | elif handle_forks == 'delete_forks': |
|
145 | 151 | h.flash(_('Deleted %s forks') % _forks, category='success') |
|
146 | 152 | |
|
147 | 153 | repo = audit_logger.RepoWrap(repo_id=None, repo_name=self.db_repo.repo_name) |
|
148 | 154 | audit_logger.store_web( |
|
149 | 155 | 'repo.delete', action_data={'old_data': old_data}, |
|
150 | 156 | user=self._rhodecode_user, repo=repo) |
|
151 | 157 | |
|
152 | 158 | ScmModel().mark_for_invalidation(self.db_repo_name, delete=True) |
|
153 | 159 | h.flash( |
|
154 | 160 | _('Deleted repository `%s`') % self.db_repo_name, |
|
155 | 161 | category='success') |
|
156 | 162 | Session().commit() |
|
157 | 163 | except AttachedForksError: |
|
158 | 164 | repo_advanced_url = h.route_path( |
|
159 | 165 | 'edit_repo_advanced', repo_name=self.db_repo_name, |
|
160 | 166 | _anchor='advanced-delete') |
|
161 | 167 | delete_anchor = h.link_to(_('detach or delete'), repo_advanced_url) |
|
162 | 168 | h.flash(_('Cannot delete `{repo}` it still contains attached forks. ' |
|
163 | 169 | 'Try using {delete_or_detach} option.') |
|
164 | 170 | .format(repo=self.db_repo_name, delete_or_detach=delete_anchor), |
|
165 | 171 | category='warning') |
|
166 | 172 | |
|
167 | 173 | # redirect to advanced for forks handle action ? |
|
168 | 174 | raise HTTPFound(repo_advanced_url) |
|
169 | 175 | |
|
170 | 176 | except AttachedPullRequestsError: |
|
171 | 177 | repo_advanced_url = h.route_path( |
|
172 | 178 | 'edit_repo_advanced', repo_name=self.db_repo_name, |
|
173 | 179 | _anchor='advanced-delete') |
|
174 | 180 | attached_prs = len(self.db_repo.pull_requests_source + |
|
175 | 181 | self.db_repo.pull_requests_target) |
|
176 | 182 | h.flash( |
|
177 | 183 | _('Cannot delete `{repo}` it still contains {num} attached pull requests. ' |
|
178 | 184 | 'Consider archiving the repository instead.').format( |
|
179 | 185 | repo=self.db_repo_name, num=attached_prs), category='warning') |
|
180 | 186 | |
|
181 | 187 | # redirect to advanced for forks handle action ? |
|
182 | 188 | raise HTTPFound(repo_advanced_url) |
|
183 | 189 | |
|
184 | 190 | except Exception: |
|
185 | 191 | log.exception("Exception during deletion of repository") |
|
186 | 192 | h.flash(_('An error occurred during deletion of `%s`') |
|
187 | 193 | % self.db_repo_name, category='error') |
|
188 | 194 | # redirect to advanced for more deletion options |
|
189 | 195 | raise HTTPFound( |
|
190 | 196 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name, |
|
191 | 197 | _anchor='advanced-delete')) |
|
192 | 198 | |
|
193 | 199 | raise HTTPFound(h.route_path('home')) |
|
194 | 200 | |
|
195 | 201 | @LoginRequired() |
|
196 | 202 | @HasRepoPermissionAnyDecorator('repository.admin') |
|
197 | 203 | @CSRFRequired() |
|
198 | 204 | @view_config( |
|
199 | 205 | route_name='edit_repo_advanced_journal', request_method='POST', |
|
200 | 206 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') |
|
201 | 207 | def edit_advanced_journal(self): |
|
202 | 208 | """ |
|
203 | 209 | Set's this repository to be visible in public journal, |
|
204 | 210 | in other words making default user to follow this repo |
|
205 | 211 | """ |
|
206 | 212 | _ = self.request.translate |
|
207 | 213 | |
|
208 | 214 | try: |
|
209 | 215 | user_id = User.get_default_user().user_id |
|
210 | 216 | ScmModel().toggle_following_repo(self.db_repo.repo_id, user_id) |
|
211 | 217 | h.flash(_('Updated repository visibility in public journal'), |
|
212 | 218 | category='success') |
|
213 | 219 | Session().commit() |
|
214 | 220 | except Exception: |
|
215 | 221 | h.flash(_('An error occurred during setting this ' |
|
216 | 222 | 'repository in public journal'), |
|
217 | 223 | category='error') |
|
218 | 224 | |
|
219 | 225 | raise HTTPFound( |
|
220 | 226 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name)) |
|
221 | 227 | |
|
222 | 228 | @LoginRequired() |
|
223 | 229 | @HasRepoPermissionAnyDecorator('repository.admin') |
|
224 | 230 | @CSRFRequired() |
|
225 | 231 | @view_config( |
|
226 | 232 | route_name='edit_repo_advanced_fork', request_method='POST', |
|
227 | 233 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') |
|
228 | 234 | def edit_advanced_fork(self): |
|
229 | 235 | """ |
|
230 | 236 | Mark given repository as a fork of another |
|
231 | 237 | """ |
|
232 | 238 | _ = self.request.translate |
|
233 | 239 | |
|
234 | 240 | new_fork_id = safe_int(self.request.POST.get('id_fork_of')) |
|
235 | 241 | |
|
236 | 242 | # valid repo, re-check permissions |
|
237 | 243 | if new_fork_id: |
|
238 | 244 | repo = Repository.get(new_fork_id) |
|
239 | 245 | # ensure we have at least read access to the repo we mark |
|
240 | 246 | perm_check = HasRepoPermissionAny( |
|
241 | 247 | 'repository.read', 'repository.write', 'repository.admin') |
|
242 | 248 | |
|
243 | 249 | if repo and perm_check(repo_name=repo.repo_name): |
|
244 | 250 | new_fork_id = repo.repo_id |
|
245 | 251 | else: |
|
246 | 252 | new_fork_id = None |
|
247 | 253 | |
|
248 | 254 | try: |
|
249 | 255 | repo = ScmModel().mark_as_fork( |
|
250 | 256 | self.db_repo_name, new_fork_id, self._rhodecode_user.user_id) |
|
251 | 257 | fork = repo.fork.repo_name if repo.fork else _('Nothing') |
|
252 | 258 | Session().commit() |
|
253 | 259 | h.flash( |
|
254 | 260 | _('Marked repo %s as fork of %s') % (self.db_repo_name, fork), |
|
255 | 261 | category='success') |
|
256 | 262 | except RepositoryError as e: |
|
257 | 263 | log.exception("Repository Error occurred") |
|
258 | 264 | h.flash(str(e), category='error') |
|
259 | 265 | except Exception: |
|
260 | 266 | log.exception("Exception while editing fork") |
|
261 | 267 | h.flash(_('An error occurred during this operation'), |
|
262 | 268 | category='error') |
|
263 | 269 | |
|
264 | 270 | raise HTTPFound( |
|
265 | 271 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name)) |
|
266 | 272 | |
|
267 | 273 | @LoginRequired() |
|
268 | 274 | @HasRepoPermissionAnyDecorator('repository.admin') |
|
269 | 275 | @CSRFRequired() |
|
270 | 276 | @view_config( |
|
271 | 277 | route_name='edit_repo_advanced_locking', request_method='POST', |
|
272 | 278 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') |
|
273 | 279 | def edit_advanced_locking(self): |
|
274 | 280 | """ |
|
275 | 281 | Toggle locking of repository |
|
276 | 282 | """ |
|
277 | 283 | _ = self.request.translate |
|
278 | 284 | set_lock = self.request.POST.get('set_lock') |
|
279 | 285 | set_unlock = self.request.POST.get('set_unlock') |
|
280 | 286 | |
|
281 | 287 | try: |
|
282 | 288 | if set_lock: |
|
283 | 289 | Repository.lock(self.db_repo, self._rhodecode_user.user_id, |
|
284 | 290 | lock_reason=Repository.LOCK_WEB) |
|
285 | 291 | h.flash(_('Locked repository'), category='success') |
|
286 | 292 | elif set_unlock: |
|
287 | 293 | Repository.unlock(self.db_repo) |
|
288 | 294 | h.flash(_('Unlocked repository'), category='success') |
|
289 | 295 | except Exception as e: |
|
290 | 296 | log.exception("Exception during unlocking") |
|
291 | 297 | h.flash(_('An error occurred during unlocking'), category='error') |
|
292 | 298 | |
|
293 | 299 | raise HTTPFound( |
|
294 | 300 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name)) |
|
295 | 301 | |
|
296 | 302 | @LoginRequired() |
|
297 | 303 | @HasRepoPermissionAnyDecorator('repository.admin') |
|
298 | 304 | @view_config( |
|
299 | 305 | route_name='edit_repo_advanced_hooks', request_method='GET', |
|
300 | 306 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') |
|
301 | 307 | def edit_advanced_install_hooks(self): |
|
302 | 308 | """ |
|
303 | 309 | Install Hooks for repository |
|
304 | 310 | """ |
|
305 | 311 | _ = self.request.translate |
|
306 | 312 | self.load_default_context() |
|
307 | 313 | self.rhodecode_vcs_repo.install_hooks(force=True) |
|
308 | 314 | h.flash(_('installed updated hooks into this repository'), |
|
309 | 315 | category='success') |
|
310 | 316 | raise HTTPFound( |
|
311 | 317 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name)) |
@@ -1,71 +1,74 b'' | |||
|
1 | 1 | <%namespace name="base" file="/base/base.mako"/> |
|
2 | 2 | |
|
3 | 3 | <% |
|
4 | 4 | source_repo_id = c.repo_group.changeset_cache.get('source_repo_id') |
|
5 | 5 | |
|
6 | 6 | elems = [ |
|
7 | 7 | (_('Repository Group ID'), c.repo_group.group_id, '', ''), |
|
8 | 8 | (_('Owner'), lambda:base.gravatar_with_user(c.repo_group.user.email, tooltip=True), '', ''), |
|
9 | 9 | (_('Created on'), h.format_date(c.repo_group.created_on), '', ''), |
|
10 | 10 | (_('Updated on'), h.format_date(c.repo_group.updated_on), '', ''), |
|
11 | (_('Cached Commit source'), (h.link_to_if(source_repo_id, 'repo_id:{}'.format(source_repo_id), h.route_path('repo_summary', repo_name='_{}'.format(source_repo_id)))), '', ''), | |
|
12 | (_('Cached Commit id'), c.repo_group.changeset_cache.get('short_id'), '', ''), | |
|
11 | 13 | (_('Cached Commit date'), (c.repo_group.changeset_cache.get('date')), '', ''), |
|
12 | (_('Cached Commit repo_id'), (h.link_to_if(source_repo_id, source_repo_id, h.route_path('repo_summary', repo_name='_{}'.format(source_repo_id)))), '', ''), | |
|
14 | ||
|
15 | (_('Cached Commit data'), lambda: h.link_to('refresh now', h.current_route_path(request, update_commit_cache=1)), '', ''), | |
|
13 | 16 | |
|
14 | 17 | (_('Is Personal Group'), c.repo_group.personal or False, '', ''), |
|
15 | 18 | |
|
16 | 19 | (_('Total repositories'), c.repo_group.repositories_recursive_count, '', ''), |
|
17 | 20 | (_('Top level repositories'), c.repo_group.repositories.count(), '', c.repo_group.repositories.all()), |
|
18 | 21 | |
|
19 | 22 | (_('Children groups'), c.repo_group.children.count(), '', c.repo_group.children.all()), |
|
20 | 23 | ] |
|
21 | 24 | %> |
|
22 | 25 | |
|
23 | 26 | <div class="panel panel-default"> |
|
24 | 27 | <div class="panel-heading"> |
|
25 | 28 | <h3 class="panel-title">${_('Repository Group Advanced: {}').format(c.repo_group.name)}</h3> |
|
26 | 29 | </div> |
|
27 | 30 | <div class="panel-body"> |
|
28 | 31 | ${base.dt_info_panel(elems)} |
|
29 | 32 | </div> |
|
30 | 33 | |
|
31 | 34 | </div> |
|
32 | 35 | |
|
33 | 36 | <div class="panel panel-danger"> |
|
34 | 37 | <div class="panel-heading"> |
|
35 | 38 | <h3 class="panel-title">${_('Delete repository group')}</h3> |
|
36 | 39 | </div> |
|
37 | 40 | <div class="panel-body"> |
|
38 | 41 | ${h.secure_form(h.route_path('edit_repo_group_advanced_delete', repo_group_name=c.repo_group.group_name), request=request)} |
|
39 | 42 | <table class="display"> |
|
40 | 43 | |
|
41 | 44 | <tr> |
|
42 | 45 | <td> |
|
43 | 46 | ${_ungettext('This repository group includes %s children repository group.', 'This repository group includes %s children repository groups.', c.repo_group.children.count()) % c.repo_group.children.count()} |
|
44 | 47 | </td> |
|
45 | 48 | <td> |
|
46 | 49 | </td> |
|
47 | 50 | <td> |
|
48 | 51 | </td> |
|
49 | 52 | </tr> |
|
50 | 53 | <tr> |
|
51 | 54 | <td> |
|
52 | 55 | ${_ungettext('This repository group includes %s repository.', 'This repository group includes %s repositories.', c.repo_group.repositories_recursive_count) % c.repo_group.repositories_recursive_count} |
|
53 | 56 | </td> |
|
54 | 57 | <td> |
|
55 | 58 | </td> |
|
56 | 59 | <td> |
|
57 | 60 | </td> |
|
58 | 61 | </tr> |
|
59 | 62 | |
|
60 | 63 | </table> |
|
61 | 64 | <div style="margin: 0 0 20px 0" class="fake-space"></div> |
|
62 | 65 | |
|
63 | 66 | <button class="btn btn-small btn-danger" type="submit" |
|
64 | 67 | onclick="return confirm('${_('Confirm to delete this group: %s') % (c.repo_group.group_name)}');"> |
|
65 | 68 | ${_('Delete this repository group')} |
|
66 | 69 | </button> |
|
67 | 70 | ${h.end_form()} |
|
68 | 71 | </div> |
|
69 | 72 | </div> |
|
70 | 73 | |
|
71 | 74 |
@@ -1,289 +1,290 b'' | |||
|
1 | 1 | <%namespace name="base" file="/base/base.mako"/> |
|
2 | 2 | |
|
3 | 3 | <% |
|
4 | 4 | elems = [ |
|
5 | 5 | (_('Repository ID'), c.rhodecode_db_repo.repo_id, '', ''), |
|
6 | 6 | (_('Owner'), lambda:base.gravatar_with_user(c.rhodecode_db_repo.user.email, tooltip=True), '', ''), |
|
7 | 7 | (_('Created on'), h.format_date(c.rhodecode_db_repo.created_on), '', ''), |
|
8 | 8 | (_('Updated on'), h.format_date(c.rhodecode_db_repo.updated_on), '', ''), |
|
9 | 9 | (_('Cached Commit id'), lambda: h.link_to(c.rhodecode_db_repo.changeset_cache.get('short_id'), h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.rhodecode_db_repo.changeset_cache.get('raw_id'))), '', ''), |
|
10 | 10 | (_('Cached Commit date'), c.rhodecode_db_repo.changeset_cache.get('date'), '', ''), |
|
11 | (_('Cached Commit data'), lambda: h.link_to('refresh now', h.current_route_path(request, update_commit_cache=1)), '', ''), | |
|
11 | 12 | (_('Attached scoped tokens'), len(c.rhodecode_db_repo.scoped_tokens), '', [x.user for x in c.rhodecode_db_repo.scoped_tokens]), |
|
12 | 13 | (_('Pull requests source'), len(c.rhodecode_db_repo.pull_requests_source), '', ['pr_id:{}, repo:{}'.format(x.pull_request_id,x.source_repo.repo_name) for x in c.rhodecode_db_repo.pull_requests_source]), |
|
13 | 14 | (_('Pull requests target'), len(c.rhodecode_db_repo.pull_requests_target), '', ['pr_id:{}, repo:{}'.format(x.pull_request_id,x.target_repo.repo_name) for x in c.rhodecode_db_repo.pull_requests_target]), |
|
14 | 15 | (_('Attached Artifacts'), len(c.rhodecode_db_repo.artifacts), '', ''), |
|
15 | 16 | ] |
|
16 | 17 | %> |
|
17 | 18 | |
|
18 | 19 | <div class="panel panel-default"> |
|
19 | 20 | <div class="panel-heading" id="advanced-info" > |
|
20 | 21 | <h3 class="panel-title">${_('Repository: %s') % c.rhodecode_db_repo.repo_name} <a class="permalink" href="#advanced-info"> ΒΆ</a></h3> |
|
21 | 22 | </div> |
|
22 | 23 | <div class="panel-body"> |
|
23 | 24 | ${base.dt_info_panel(elems)} |
|
24 | 25 | </div> |
|
25 | 26 | </div> |
|
26 | 27 | |
|
27 | 28 | |
|
28 | 29 | <div class="panel panel-default"> |
|
29 | 30 | <div class="panel-heading" id="advanced-fork"> |
|
30 | 31 | <h3 class="panel-title">${_('Fork Reference')} <a class="permalink" href="#advanced-fork"> ΒΆ</a></h3> |
|
31 | 32 | </div> |
|
32 | 33 | <div class="panel-body"> |
|
33 | 34 | ${h.secure_form(h.route_path('edit_repo_advanced_fork', repo_name=c.rhodecode_db_repo.repo_name), request=request)} |
|
34 | 35 | |
|
35 | 36 | % if c.rhodecode_db_repo.fork: |
|
36 | 37 | <div class="panel-body-title-text">${h.literal(_('This repository is a fork of %(repo_link)s') % {'repo_link': h.link_to_if(c.has_origin_repo_read_perm,c.rhodecode_db_repo.fork.repo_name, h.route_path('repo_summary', repo_name=c.rhodecode_db_repo.fork.repo_name))})} |
|
37 | 38 | | <button class="btn btn-link btn-danger" type="submit">Remove fork reference</button></div> |
|
38 | 39 | % endif |
|
39 | 40 | |
|
40 | 41 | <div class="field"> |
|
41 | 42 | ${h.hidden('id_fork_of')} |
|
42 | 43 | ${h.submit('set_as_fork_%s' % c.rhodecode_db_repo.repo_name,_('Set'),class_="btn btn-small",)} |
|
43 | 44 | </div> |
|
44 | 45 | <div class="field"> |
|
45 | 46 | <span class="help-block">${_('Manually set this repository as a fork of another from the list')}</span> |
|
46 | 47 | </div> |
|
47 | 48 | ${h.end_form()} |
|
48 | 49 | </div> |
|
49 | 50 | </div> |
|
50 | 51 | |
|
51 | 52 | |
|
52 | 53 | <div class="panel panel-default"> |
|
53 | 54 | <div class="panel-heading" id="advanced-journal"> |
|
54 | 55 | <h3 class="panel-title">${_('Public Journal Visibility')} <a class="permalink" href="#advanced-journal"> ΒΆ</a></h3> |
|
55 | 56 | </div> |
|
56 | 57 | <div class="panel-body"> |
|
57 | 58 | ${h.secure_form(h.route_path('edit_repo_advanced_journal', repo_name=c.rhodecode_db_repo.repo_name), request=request)} |
|
58 | 59 | <div class="field"> |
|
59 | 60 | %if c.in_public_journal: |
|
60 | 61 | <button class="btn btn-small" type="submit"> |
|
61 | 62 | ${_('Remove from Public Journal')} |
|
62 | 63 | </button> |
|
63 | 64 | %else: |
|
64 | 65 | <button class="btn btn-small" type="submit"> |
|
65 | 66 | ${_('Add to Public Journal')} |
|
66 | 67 | </button> |
|
67 | 68 | %endif |
|
68 | 69 | </div> |
|
69 | 70 | <div class="field" > |
|
70 | 71 | <span class="help-block">${_('All actions made on this repository will be visible to everyone following the public journal.')}</span> |
|
71 | 72 | </div> |
|
72 | 73 | ${h.end_form()} |
|
73 | 74 | </div> |
|
74 | 75 | </div> |
|
75 | 76 | |
|
76 | 77 | |
|
77 | 78 | <div class="panel panel-default"> |
|
78 | 79 | <div class="panel-heading" id="advanced-locking"> |
|
79 | 80 | <h3 class="panel-title">${_('Locking state')} <a class="permalink" href="#advanced-locking"> ΒΆ</a></h3> |
|
80 | 81 | </div> |
|
81 | 82 | <div class="panel-body"> |
|
82 | 83 | ${h.secure_form(h.route_path('edit_repo_advanced_locking', repo_name=c.rhodecode_db_repo.repo_name), request=request)} |
|
83 | 84 | |
|
84 | 85 | %if c.rhodecode_db_repo.locked[0]: |
|
85 | 86 | <div class="panel-body-title-text">${'Locked by %s on %s. Lock reason: %s' % (h.person_by_id(c.rhodecode_db_repo.locked[0]), |
|
86 | 87 | h.format_date(h. time_to_datetime(c.rhodecode_db_repo.locked[1])), c.rhodecode_db_repo.locked[2])}</div> |
|
87 | 88 | %else: |
|
88 | 89 | <div class="panel-body-title-text">${_('This Repository is not currently locked.')}</div> |
|
89 | 90 | %endif |
|
90 | 91 | |
|
91 | 92 | <div class="field" > |
|
92 | 93 | %if c.rhodecode_db_repo.locked[0]: |
|
93 | 94 | ${h.hidden('set_unlock', '1')} |
|
94 | 95 | <button class="btn btn-small" type="submit" |
|
95 | 96 | onclick="return confirm('${_('Confirm to unlock repository.')}');"> |
|
96 | 97 | <i class="icon-unlock"></i> |
|
97 | 98 | ${_('Unlock repository')} |
|
98 | 99 | </button> |
|
99 | 100 | %else: |
|
100 | 101 | ${h.hidden('set_lock', '1')} |
|
101 | 102 | <button class="btn btn-small" type="submit" |
|
102 | 103 | onclick="return confirm('${_('Confirm to lock repository.')}');"> |
|
103 | 104 | <i class="icon-lock"></i> |
|
104 | 105 | ${_('Lock repository')} |
|
105 | 106 | </button> |
|
106 | 107 | %endif |
|
107 | 108 | </div> |
|
108 | 109 | <div class="field" > |
|
109 | 110 | <span class="help-block"> |
|
110 | 111 | ${_('Force repository locking. This only works when anonymous access is disabled. Pulling from the repository locks the repository to that user until the same user pushes to that repository again.')} |
|
111 | 112 | </span> |
|
112 | 113 | </div> |
|
113 | 114 | ${h.end_form()} |
|
114 | 115 | </div> |
|
115 | 116 | </div> |
|
116 | 117 | |
|
117 | 118 | |
|
118 | 119 | <div class="panel panel-default"> |
|
119 | 120 | <div class="panel-heading" id="advanced-hooks"> |
|
120 | 121 | <h3 class="panel-title">${_('Hooks')} <a class="permalink" href="#advanced-hooks"> ΒΆ</a></h3> |
|
121 | 122 | </div> |
|
122 | 123 | <div class="panel-body"> |
|
123 | 124 | <table class="rctable"> |
|
124 | 125 | <th>${_('Hook type')}</th> |
|
125 | 126 | <th>${_('Hook version')}</th> |
|
126 | 127 | <th>${_('Current version')}</th> |
|
127 | 128 | % if c.ver_info_dict: |
|
128 | 129 | <tr> |
|
129 | 130 | <td>${_('PRE HOOK')}</td> |
|
130 | 131 | <td>${c.ver_info_dict['pre_version']}</td> |
|
131 | 132 | <td>${c.rhodecode_version}</td> |
|
132 | 133 | </tr> |
|
133 | 134 | <tr> |
|
134 | 135 | <td>${_('POST HOOK')}</td> |
|
135 | 136 | <td>${c.ver_info_dict['post_version']}</td> |
|
136 | 137 | <td>${c.rhodecode_version}</td> |
|
137 | 138 | </tr> |
|
138 | 139 | % else: |
|
139 | 140 | <tr> |
|
140 | 141 | <td>${_('Unable to read hook information from VCS Server')}</td> |
|
141 | 142 | </tr> |
|
142 | 143 | % endif |
|
143 | 144 | </table> |
|
144 | 145 | |
|
145 | 146 | <a class="btn btn-primary" href="${h.route_path('edit_repo_advanced_hooks', repo_name=c.repo_name)}" |
|
146 | 147 | onclick="return confirm('${_('Confirm to reinstall hooks for this repository.')}');"> |
|
147 | 148 | ${_('Update Hooks')} |
|
148 | 149 | </a> |
|
149 | 150 | </div> |
|
150 | 151 | </div> |
|
151 | 152 | |
|
152 | 153 | <div class="panel panel-warning"> |
|
153 | 154 | <div class="panel-heading" id="advanced-archive"> |
|
154 | 155 | <h3 class="panel-title">${_('Archive repository')} <a class="permalink" href="#advanced-archive"> ΒΆ</a></h3> |
|
155 | 156 | </div> |
|
156 | 157 | <div class="panel-body"> |
|
157 | 158 | ${h.secure_form(h.route_path('edit_repo_advanced_archive', repo_name=c.repo_name), request=request)} |
|
158 | 159 | |
|
159 | 160 | <div style="margin: 0 0 20px 0" class="fake-space"></div> |
|
160 | 161 | |
|
161 | 162 | <div class="field"> |
|
162 | 163 | <button class="btn btn-small btn-warning" type="submit" |
|
163 | 164 | onclick="return confirm('${_('Confirm to archive this repository: %s') % c.repo_name}');"> |
|
164 | 165 | ${_('Archive this repository')} |
|
165 | 166 | </button> |
|
166 | 167 | </div> |
|
167 | 168 | <div class="field"> |
|
168 | 169 | <span class="help-block"> |
|
169 | 170 | ${_('Archiving the repository will make it entirely read-only. The repository cannot be committed to.' |
|
170 | 171 | 'It is hidden from the search results and dashboard. ')} |
|
171 | 172 | </span> |
|
172 | 173 | </div> |
|
173 | 174 | |
|
174 | 175 | ${h.end_form()} |
|
175 | 176 | </div> |
|
176 | 177 | </div> |
|
177 | 178 | |
|
178 | 179 | |
|
179 | 180 | <div class="panel panel-danger"> |
|
180 | 181 | <div class="panel-heading" id="advanced-delete"> |
|
181 | 182 | <h3 class="panel-title">${_('Delete repository')} <a class="permalink" href="#advanced-delete"> ΒΆ</a></h3> |
|
182 | 183 | </div> |
|
183 | 184 | <div class="panel-body"> |
|
184 | 185 | ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=c.repo_name), request=request)} |
|
185 | 186 | <table class="display"> |
|
186 | 187 | <tr> |
|
187 | 188 | <td> |
|
188 | 189 | ${_ungettext('This repository has %s fork.', 'This repository has %s forks.', c.rhodecode_db_repo.forks.count()) % c.rhodecode_db_repo.forks.count()} |
|
189 | 190 | </td> |
|
190 | 191 | <td> |
|
191 | 192 | %if c.rhodecode_db_repo.forks.count(): |
|
192 | 193 | <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label> |
|
193 | 194 | %endif |
|
194 | 195 | </td> |
|
195 | 196 | <td> |
|
196 | 197 | %if c.rhodecode_db_repo.forks.count(): |
|
197 | 198 | <input type="radio" name="forks" value="delete_forks"/> <label for="forks">${_('Delete forks')}</label> |
|
198 | 199 | %endif |
|
199 | 200 | </td> |
|
200 | 201 | </tr> |
|
201 | 202 | <% attached_prs = len(c.rhodecode_db_repo.pull_requests_source + c.rhodecode_db_repo.pull_requests_target) %> |
|
202 | 203 | % if c.rhodecode_db_repo.pull_requests_source or c.rhodecode_db_repo.pull_requests_target: |
|
203 | 204 | <tr> |
|
204 | 205 | <td> |
|
205 | 206 | ${_ungettext('This repository has %s attached pull request.', 'This repository has %s attached pull requests.', attached_prs) % attached_prs} |
|
206 | 207 | <br/> |
|
207 | 208 | ${_('Consider to archive this repository instead.')} |
|
208 | 209 | </td> |
|
209 | 210 | <td></td> |
|
210 | 211 | <td></td> |
|
211 | 212 | </tr> |
|
212 | 213 | % endif |
|
213 | 214 | </table> |
|
214 | 215 | <div style="margin: 0 0 20px 0" class="fake-space"></div> |
|
215 | 216 | |
|
216 | 217 | <div class="field"> |
|
217 | 218 | <button class="btn btn-small btn-danger" type="submit" |
|
218 | 219 | onclick="return confirm('${_('Confirm to delete this repository: %s') % c.repo_name}');"> |
|
219 | 220 | ${_('Delete this repository')} |
|
220 | 221 | </button> |
|
221 | 222 | </div> |
|
222 | 223 | <div class="field"> |
|
223 | 224 | <span class="help-block"> |
|
224 | 225 | ${_('This repository will be renamed in a special way in order to make it inaccessible to RhodeCode Enterprise and its VCS systems. If you need to fully delete it from the file system, please do it manually, or with rhodecode-cleanup-repos command available in rhodecode-tools.')} |
|
225 | 226 | </span> |
|
226 | 227 | </div> |
|
227 | 228 | |
|
228 | 229 | ${h.end_form()} |
|
229 | 230 | </div> |
|
230 | 231 | </div> |
|
231 | 232 | |
|
232 | 233 | |
|
233 | 234 | <script> |
|
234 | 235 | |
|
235 | 236 | var currentRepoId = ${c.rhodecode_db_repo.repo_id}; |
|
236 | 237 | |
|
237 | 238 | var repoTypeFilter = function(data) { |
|
238 | 239 | var results = []; |
|
239 | 240 | |
|
240 | 241 | if (!data.results[0]) { |
|
241 | 242 | return data |
|
242 | 243 | } |
|
243 | 244 | |
|
244 | 245 | $.each(data.results[0].children, function() { |
|
245 | 246 | // filter out the SAME repo, it cannot be used as fork of itself |
|
246 | 247 | if (this.repo_id != currentRepoId) { |
|
247 | 248 | this.id = this.repo_id; |
|
248 | 249 | results.push(this) |
|
249 | 250 | } |
|
250 | 251 | }); |
|
251 | 252 | data.results[0].children = results; |
|
252 | 253 | return data; |
|
253 | 254 | }; |
|
254 | 255 | |
|
255 | 256 | $("#id_fork_of").select2({ |
|
256 | 257 | cachedDataSource: {}, |
|
257 | 258 | minimumInputLength: 2, |
|
258 | 259 | placeholder: "${_('Change repository') if c.rhodecode_db_repo.fork else _('Pick repository')}", |
|
259 | 260 | dropdownAutoWidth: true, |
|
260 | 261 | containerCssClass: "drop-menu", |
|
261 | 262 | dropdownCssClass: "drop-menu-dropdown", |
|
262 | 263 | formatResult: formatRepoResult, |
|
263 | 264 | query: $.debounce(250, function(query){ |
|
264 | 265 | self = this; |
|
265 | 266 | var cacheKey = query.term; |
|
266 | 267 | var cachedData = self.cachedDataSource[cacheKey]; |
|
267 | 268 | |
|
268 | 269 | if (cachedData) { |
|
269 | 270 | query.callback({results: cachedData.results}); |
|
270 | 271 | } else { |
|
271 | 272 | $.ajax({ |
|
272 | 273 | url: pyroutes.url('repo_list_data'), |
|
273 | 274 | data: {'query': query.term, repo_type: '${c.rhodecode_db_repo.repo_type}'}, |
|
274 | 275 | dataType: 'json', |
|
275 | 276 | type: 'GET', |
|
276 | 277 | success: function(data) { |
|
277 | 278 | data = repoTypeFilter(data); |
|
278 | 279 | self.cachedDataSource[cacheKey] = data; |
|
279 | 280 | query.callback({results: data.results}); |
|
280 | 281 | }, |
|
281 | 282 | error: function(data, textStatus, errorThrown) { |
|
282 | 283 | alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText)); |
|
283 | 284 | } |
|
284 | 285 | }) |
|
285 | 286 | } |
|
286 | 287 | }) |
|
287 | 288 | }); |
|
288 | 289 | </script> |
|
289 | 290 |
General Comments 0
You need to be logged in to leave comments.
Login now