##// END OF EJS Templates
fixes issue when owner of a repo couldn't revoke permissions for users and groups
marcink -
r1829:6f8f1ab2 default
parent child Browse files
Show More
@@ -1,397 +1,398
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.repos
3 rhodecode.controllers.admin.repos
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Admin controller for RhodeCode
6 Admin controller for RhodeCode
7
7
8 :created_on: Apr 7, 2010
8 :created_on: Apr 7, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29 from formencode import htmlfill
29 from formencode import htmlfill
30
30
31 from paste.httpexceptions import HTTPInternalServerError
31 from paste.httpexceptions import HTTPInternalServerError
32 from pylons import request, response, session, tmpl_context as c, url
32 from pylons import request, response, session, tmpl_context as c, url
33 from pylons.controllers.util import abort, redirect
33 from pylons.controllers.util import abort, redirect
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35
35
36 from rhodecode.lib import helpers as h
36 from rhodecode.lib import helpers as h
37 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
37 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
38 HasPermissionAnyDecorator
38 HasPermissionAnyDecorator, HasRepoPermissionAllDecorator
39 from rhodecode.lib.base import BaseController, render
39 from rhodecode.lib.base import BaseController, render
40 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
40 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
41 from rhodecode.lib.helpers import get_token
41 from rhodecode.lib.helpers import get_token
42 from rhodecode.model.db import User, Repository, UserFollowing, Group
42 from rhodecode.model.db import User, Repository, UserFollowing, Group
43 from rhodecode.model.forms import RepoForm
43 from rhodecode.model.forms import RepoForm
44 from rhodecode.model.scm import ScmModel
44 from rhodecode.model.scm import ScmModel
45 from rhodecode.model.repo import RepoModel
45 from rhodecode.model.repo import RepoModel
46 from sqlalchemy.exc import IntegrityError
46 from sqlalchemy.exc import IntegrityError
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50
50
51 class ReposController(BaseController):
51 class ReposController(BaseController):
52 """
52 """
53 REST Controller styled on the Atom Publishing Protocol"""
53 REST Controller styled on the Atom Publishing Protocol"""
54 # To properly map this controller, ensure your config/routing.py
54 # To properly map this controller, ensure your config/routing.py
55 # file has a resource setup:
55 # file has a resource setup:
56 # map.resource('repo', 'repos')
56 # map.resource('repo', 'repos')
57
57
58 @LoginRequired()
58 @LoginRequired()
59 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
59 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
60 def __before__(self):
60 def __before__(self):
61 c.admin_user = session.get('admin_user')
61 c.admin_user = session.get('admin_user')
62 c.admin_username = session.get('admin_username')
62 c.admin_username = session.get('admin_username')
63 super(ReposController, self).__before__()
63 super(ReposController, self).__before__()
64
64
65 def __load_defaults(self):
65 def __load_defaults(self):
66 c.repo_groups = Group.groups_choices()
66 c.repo_groups = Group.groups_choices()
67 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
67 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
68
68
69 repo_model = RepoModel()
69 repo_model = RepoModel()
70 c.users_array = repo_model.get_users_js()
70 c.users_array = repo_model.get_users_js()
71 c.users_groups_array = repo_model.get_users_groups_js()
71 c.users_groups_array = repo_model.get_users_groups_js()
72
72
73 def __load_data(self, repo_name=None):
73 def __load_data(self, repo_name=None):
74 """
74 """
75 Load defaults settings for edit, and update
75 Load defaults settings for edit, and update
76
76
77 :param repo_name:
77 :param repo_name:
78 """
78 """
79 self.__load_defaults()
79 self.__load_defaults()
80
80
81 c.repo_info = db_repo = Repository.get_by_repo_name(repo_name)
81 c.repo_info = db_repo = Repository.get_by_repo_name(repo_name)
82 repo = db_repo.scm_instance
82 repo = db_repo.scm_instance
83
83
84 if c.repo_info is None:
84 if c.repo_info is None:
85 h.flash(_('%s repository is not mapped to db perhaps'
85 h.flash(_('%s repository is not mapped to db perhaps'
86 ' it was created or renamed from the filesystem'
86 ' it was created or renamed from the filesystem'
87 ' please run the application again'
87 ' please run the application again'
88 ' in order to rescan repositories') % repo_name,
88 ' in order to rescan repositories') % repo_name,
89 category='error')
89 category='error')
90
90
91 return redirect(url('repos'))
91 return redirect(url('repos'))
92
92
93 c.default_user_id = User.get_by_username('default').user_id
93 c.default_user_id = User.get_by_username('default').user_id
94 c.in_public_journal = UserFollowing.query()\
94 c.in_public_journal = UserFollowing.query()\
95 .filter(UserFollowing.user_id == c.default_user_id)\
95 .filter(UserFollowing.user_id == c.default_user_id)\
96 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
96 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
97
97
98 if c.repo_info.stats:
98 if c.repo_info.stats:
99 last_rev = c.repo_info.stats.stat_on_revision
99 last_rev = c.repo_info.stats.stat_on_revision
100 else:
100 else:
101 last_rev = 0
101 last_rev = 0
102 c.stats_revision = last_rev
102 c.stats_revision = last_rev
103
103
104 c.repo_last_rev = repo.count() - 1 if repo.revisions else 0
104 c.repo_last_rev = repo.count() - 1 if repo.revisions else 0
105
105
106 if last_rev == 0 or c.repo_last_rev == 0:
106 if last_rev == 0 or c.repo_last_rev == 0:
107 c.stats_percentage = 0
107 c.stats_percentage = 0
108 else:
108 else:
109 c.stats_percentage = '%.2f' % ((float((last_rev)) /
109 c.stats_percentage = '%.2f' % ((float((last_rev)) /
110 c.repo_last_rev) * 100)
110 c.repo_last_rev) * 100)
111
111
112 defaults = RepoModel()._get_defaults(repo_name)
112 defaults = RepoModel()._get_defaults(repo_name)
113 return defaults
113 return defaults
114
114
115 @HasPermissionAllDecorator('hg.admin')
115 @HasPermissionAllDecorator('hg.admin')
116 def index(self, format='html'):
116 def index(self, format='html'):
117 """GET /repos: All items in the collection"""
117 """GET /repos: All items in the collection"""
118 # url('repos')
118 # url('repos')
119
119
120 c.repos_list = ScmModel().get_repos(Repository.query()
120 c.repos_list = ScmModel().get_repos(Repository.query()
121 .order_by(Repository.repo_name)
121 .order_by(Repository.repo_name)
122 .all(), sort_key='name_sort')
122 .all(), sort_key='name_sort')
123 return render('admin/repos/repos.html')
123 return render('admin/repos/repos.html')
124
124
125 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
125 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
126 def create(self):
126 def create(self):
127 """
127 """
128 POST /repos: Create a new item"""
128 POST /repos: Create a new item"""
129 # url('repos')
129 # url('repos')
130 repo_model = RepoModel()
130 repo_model = RepoModel()
131 self.__load_defaults()
131 self.__load_defaults()
132 form_result = {}
132 form_result = {}
133 try:
133 try:
134 form_result = RepoForm(repo_groups=c.repo_groups_choices)()\
134 form_result = RepoForm(repo_groups=c.repo_groups_choices)()\
135 .to_python(dict(request.POST))
135 .to_python(dict(request.POST))
136 repo_model.create(form_result, self.rhodecode_user)
136 repo_model.create(form_result, self.rhodecode_user)
137 if form_result['clone_uri']:
137 if form_result['clone_uri']:
138 h.flash(_('created repository %s from %s') \
138 h.flash(_('created repository %s from %s') \
139 % (form_result['repo_name'], form_result['clone_uri']),
139 % (form_result['repo_name'], form_result['clone_uri']),
140 category='success')
140 category='success')
141 else:
141 else:
142 h.flash(_('created repository %s') % form_result['repo_name'],
142 h.flash(_('created repository %s') % form_result['repo_name'],
143 category='success')
143 category='success')
144
144
145 if request.POST.get('user_created'):
145 if request.POST.get('user_created'):
146 #created by regular non admin user
146 #created by regular non admin user
147 action_logger(self.rhodecode_user, 'user_created_repo',
147 action_logger(self.rhodecode_user, 'user_created_repo',
148 form_result['repo_name_full'], '', self.sa)
148 form_result['repo_name_full'], '', self.sa)
149 else:
149 else:
150 action_logger(self.rhodecode_user, 'admin_created_repo',
150 action_logger(self.rhodecode_user, 'admin_created_repo',
151 form_result['repo_name_full'], '', self.sa)
151 form_result['repo_name_full'], '', self.sa)
152
152
153 except formencode.Invalid, errors:
153 except formencode.Invalid, errors:
154
154
155 c.new_repo = errors.value['repo_name']
155 c.new_repo = errors.value['repo_name']
156
156
157 if request.POST.get('user_created'):
157 if request.POST.get('user_created'):
158 r = render('admin/repos/repo_add_create_repository.html')
158 r = render('admin/repos/repo_add_create_repository.html')
159 else:
159 else:
160 r = render('admin/repos/repo_add.html')
160 r = render('admin/repos/repo_add.html')
161
161
162 return htmlfill.render(
162 return htmlfill.render(
163 r,
163 r,
164 defaults=errors.value,
164 defaults=errors.value,
165 errors=errors.error_dict or {},
165 errors=errors.error_dict or {},
166 prefix_error=False,
166 prefix_error=False,
167 encoding="UTF-8")
167 encoding="UTF-8")
168
168
169 except Exception:
169 except Exception:
170 log.error(traceback.format_exc())
170 log.error(traceback.format_exc())
171 msg = _('error occurred during creation of repository %s') \
171 msg = _('error occurred during creation of repository %s') \
172 % form_result.get('repo_name')
172 % form_result.get('repo_name')
173 h.flash(msg, category='error')
173 h.flash(msg, category='error')
174 if request.POST.get('user_created'):
174 if request.POST.get('user_created'):
175 return redirect(url('home'))
175 return redirect(url('home'))
176 return redirect(url('repos'))
176 return redirect(url('repos'))
177
177
178 @HasPermissionAllDecorator('hg.admin')
178 @HasPermissionAllDecorator('hg.admin')
179 def new(self, format='html'):
179 def new(self, format='html'):
180 """GET /repos/new: Form to create a new item"""
180 """GET /repos/new: Form to create a new item"""
181 new_repo = request.GET.get('repo', '')
181 new_repo = request.GET.get('repo', '')
182 c.new_repo = repo_name_slug(new_repo)
182 c.new_repo = repo_name_slug(new_repo)
183 self.__load_defaults()
183 self.__load_defaults()
184 return render('admin/repos/repo_add.html')
184 return render('admin/repos/repo_add.html')
185
185
186 @HasPermissionAllDecorator('hg.admin')
186 @HasPermissionAllDecorator('hg.admin')
187 def update(self, repo_name):
187 def update(self, repo_name):
188 """
188 """
189 PUT /repos/repo_name: Update an existing item"""
189 PUT /repos/repo_name: Update an existing item"""
190 # Forms posted to this method should contain a hidden field:
190 # Forms posted to this method should contain a hidden field:
191 # <input type="hidden" name="_method" value="PUT" />
191 # <input type="hidden" name="_method" value="PUT" />
192 # Or using helpers:
192 # Or using helpers:
193 # h.form(url('repo', repo_name=ID),
193 # h.form(url('repo', repo_name=ID),
194 # method='put')
194 # method='put')
195 # url('repo', repo_name=ID)
195 # url('repo', repo_name=ID)
196 self.__load_defaults()
196 self.__load_defaults()
197 repo_model = RepoModel()
197 repo_model = RepoModel()
198 changed_name = repo_name
198 changed_name = repo_name
199 _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
199 _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
200 repo_groups=c.repo_groups_choices)()
200 repo_groups=c.repo_groups_choices)()
201 try:
201 try:
202 form_result = _form.to_python(dict(request.POST))
202 form_result = _form.to_python(dict(request.POST))
203 repo = repo_model.update(repo_name, form_result)
203 repo = repo_model.update(repo_name, form_result)
204 invalidate_cache('get_repo_cached_%s' % repo_name)
204 invalidate_cache('get_repo_cached_%s' % repo_name)
205 h.flash(_('Repository %s updated successfully' % repo_name),
205 h.flash(_('Repository %s updated successfully' % repo_name),
206 category='success')
206 category='success')
207 changed_name = repo.repo_name
207 changed_name = repo.repo_name
208 action_logger(self.rhodecode_user, 'admin_updated_repo',
208 action_logger(self.rhodecode_user, 'admin_updated_repo',
209 changed_name, '', self.sa)
209 changed_name, '', self.sa)
210
210
211 except formencode.Invalid, errors:
211 except formencode.Invalid, errors:
212 defaults = self.__load_data(repo_name)
212 defaults = self.__load_data(repo_name)
213 defaults.update(errors.value)
213 defaults.update(errors.value)
214 return htmlfill.render(
214 return htmlfill.render(
215 render('admin/repos/repo_edit.html'),
215 render('admin/repos/repo_edit.html'),
216 defaults=defaults,
216 defaults=defaults,
217 errors=errors.error_dict or {},
217 errors=errors.error_dict or {},
218 prefix_error=False,
218 prefix_error=False,
219 encoding="UTF-8")
219 encoding="UTF-8")
220
220
221 except Exception:
221 except Exception:
222 log.error(traceback.format_exc())
222 log.error(traceback.format_exc())
223 h.flash(_('error occurred during update of repository %s') \
223 h.flash(_('error occurred during update of repository %s') \
224 % repo_name, category='error')
224 % repo_name, category='error')
225 return redirect(url('edit_repo', repo_name=changed_name))
225 return redirect(url('edit_repo', repo_name=changed_name))
226
226
227 @HasPermissionAllDecorator('hg.admin')
227 @HasPermissionAllDecorator('hg.admin')
228 def delete(self, repo_name):
228 def delete(self, repo_name):
229 """
229 """
230 DELETE /repos/repo_name: Delete an existing item"""
230 DELETE /repos/repo_name: Delete an existing item"""
231 # Forms posted to this method should contain a hidden field:
231 # Forms posted to this method should contain a hidden field:
232 # <input type="hidden" name="_method" value="DELETE" />
232 # <input type="hidden" name="_method" value="DELETE" />
233 # Or using helpers:
233 # Or using helpers:
234 # h.form(url('repo', repo_name=ID),
234 # h.form(url('repo', repo_name=ID),
235 # method='delete')
235 # method='delete')
236 # url('repo', repo_name=ID)
236 # url('repo', repo_name=ID)
237
237
238 repo_model = RepoModel()
238 repo_model = RepoModel()
239 repo = repo_model.get_by_repo_name(repo_name)
239 repo = repo_model.get_by_repo_name(repo_name)
240 if not repo:
240 if not repo:
241 h.flash(_('%s repository is not mapped to db perhaps'
241 h.flash(_('%s repository is not mapped to db perhaps'
242 ' it was moved or renamed from the filesystem'
242 ' it was moved or renamed from the filesystem'
243 ' please run the application again'
243 ' please run the application again'
244 ' in order to rescan repositories') % repo_name,
244 ' in order to rescan repositories') % repo_name,
245 category='error')
245 category='error')
246
246
247 return redirect(url('repos'))
247 return redirect(url('repos'))
248 try:
248 try:
249 action_logger(self.rhodecode_user, 'admin_deleted_repo',
249 action_logger(self.rhodecode_user, 'admin_deleted_repo',
250 repo_name, '', self.sa)
250 repo_name, '', self.sa)
251 repo_model.delete(repo)
251 repo_model.delete(repo)
252 invalidate_cache('get_repo_cached_%s' % repo_name)
252 invalidate_cache('get_repo_cached_%s' % repo_name)
253 h.flash(_('deleted repository %s') % repo_name, category='success')
253 h.flash(_('deleted repository %s') % repo_name, category='success')
254
254
255 except IntegrityError, e:
255 except IntegrityError, e:
256 if e.message.find('repositories_fork_id_fkey'):
256 if e.message.find('repositories_fork_id_fkey'):
257 log.error(traceback.format_exc())
257 log.error(traceback.format_exc())
258 h.flash(_('Cannot delete %s it still contains attached '
258 h.flash(_('Cannot delete %s it still contains attached '
259 'forks') % repo_name,
259 'forks') % repo_name,
260 category='warning')
260 category='warning')
261 else:
261 else:
262 log.error(traceback.format_exc())
262 log.error(traceback.format_exc())
263 h.flash(_('An error occurred during '
263 h.flash(_('An error occurred during '
264 'deletion of %s') % repo_name,
264 'deletion of %s') % repo_name,
265 category='error')
265 category='error')
266
266
267 except Exception, e:
267 except Exception, e:
268 log.error(traceback.format_exc())
268 log.error(traceback.format_exc())
269 h.flash(_('An error occurred during deletion of %s') % repo_name,
269 h.flash(_('An error occurred during deletion of %s') % repo_name,
270 category='error')
270 category='error')
271
271
272 return redirect(url('repos'))
272 return redirect(url('repos'))
273
273
274 @HasPermissionAllDecorator('hg.admin')
274
275 @HasRepoPermissionAllDecorator('repository.admin')
275 def delete_perm_user(self, repo_name):
276 def delete_perm_user(self, repo_name):
276 """
277 """
277 DELETE an existing repository permission user
278 DELETE an existing repository permission user
278
279
279 :param repo_name:
280 :param repo_name:
280 """
281 """
281
282
282 try:
283 try:
283 repo_model = RepoModel()
284 repo_model = RepoModel()
284 repo_model.delete_perm_user(request.POST, repo_name)
285 repo_model.delete_perm_user(request.POST, repo_name)
285 except Exception, e:
286 except Exception, e:
286 h.flash(_('An error occurred during deletion of repository user'),
287 h.flash(_('An error occurred during deletion of repository user'),
287 category='error')
288 category='error')
288 raise HTTPInternalServerError()
289 raise HTTPInternalServerError()
289
290
290 @HasPermissionAllDecorator('hg.admin')
291 @HasRepoPermissionAllDecorator('repository.admin')
291 def delete_perm_users_group(self, repo_name):
292 def delete_perm_users_group(self, repo_name):
292 """
293 """
293 DELETE an existing repository permission users group
294 DELETE an existing repository permission users group
294
295
295 :param repo_name:
296 :param repo_name:
296 """
297 """
297 try:
298 try:
298 repo_model = RepoModel()
299 repo_model = RepoModel()
299 repo_model.delete_perm_users_group(request.POST, repo_name)
300 repo_model.delete_perm_users_group(request.POST, repo_name)
300 except Exception, e:
301 except Exception, e:
301 h.flash(_('An error occurred during deletion of repository'
302 h.flash(_('An error occurred during deletion of repository'
302 ' users groups'),
303 ' users groups'),
303 category='error')
304 category='error')
304 raise HTTPInternalServerError()
305 raise HTTPInternalServerError()
305
306
306 @HasPermissionAllDecorator('hg.admin')
307 @HasPermissionAllDecorator('hg.admin')
307 def repo_stats(self, repo_name):
308 def repo_stats(self, repo_name):
308 """
309 """
309 DELETE an existing repository statistics
310 DELETE an existing repository statistics
310
311
311 :param repo_name:
312 :param repo_name:
312 """
313 """
313
314
314 try:
315 try:
315 repo_model = RepoModel()
316 repo_model = RepoModel()
316 repo_model.delete_stats(repo_name)
317 repo_model.delete_stats(repo_name)
317 except Exception, e:
318 except Exception, e:
318 h.flash(_('An error occurred during deletion of repository stats'),
319 h.flash(_('An error occurred during deletion of repository stats'),
319 category='error')
320 category='error')
320 return redirect(url('edit_repo', repo_name=repo_name))
321 return redirect(url('edit_repo', repo_name=repo_name))
321
322
322 @HasPermissionAllDecorator('hg.admin')
323 @HasPermissionAllDecorator('hg.admin')
323 def repo_cache(self, repo_name):
324 def repo_cache(self, repo_name):
324 """
325 """
325 INVALIDATE existing repository cache
326 INVALIDATE existing repository cache
326
327
327 :param repo_name:
328 :param repo_name:
328 """
329 """
329
330
330 try:
331 try:
331 ScmModel().mark_for_invalidation(repo_name)
332 ScmModel().mark_for_invalidation(repo_name)
332 except Exception, e:
333 except Exception, e:
333 h.flash(_('An error occurred during cache invalidation'),
334 h.flash(_('An error occurred during cache invalidation'),
334 category='error')
335 category='error')
335 return redirect(url('edit_repo', repo_name=repo_name))
336 return redirect(url('edit_repo', repo_name=repo_name))
336
337
337 @HasPermissionAllDecorator('hg.admin')
338 @HasPermissionAllDecorator('hg.admin')
338 def repo_public_journal(self, repo_name):
339 def repo_public_journal(self, repo_name):
339 """
340 """
340 Set's this repository to be visible in public journal,
341 Set's this repository to be visible in public journal,
341 in other words assing default user to follow this repo
342 in other words assing default user to follow this repo
342
343
343 :param repo_name:
344 :param repo_name:
344 """
345 """
345
346
346 cur_token = request.POST.get('auth_token')
347 cur_token = request.POST.get('auth_token')
347 token = get_token()
348 token = get_token()
348 if cur_token == token:
349 if cur_token == token:
349 try:
350 try:
350 repo_id = Repository.get_by_repo_name(repo_name).repo_id
351 repo_id = Repository.get_by_repo_name(repo_name).repo_id
351 user_id = User.get_by_username('default').user_id
352 user_id = User.get_by_username('default').user_id
352 self.scm_model.toggle_following_repo(repo_id, user_id)
353 self.scm_model.toggle_following_repo(repo_id, user_id)
353 h.flash(_('Updated repository visibility in public journal'),
354 h.flash(_('Updated repository visibility in public journal'),
354 category='success')
355 category='success')
355 except:
356 except:
356 h.flash(_('An error occurred during setting this'
357 h.flash(_('An error occurred during setting this'
357 ' repository in public journal'),
358 ' repository in public journal'),
358 category='error')
359 category='error')
359
360
360 else:
361 else:
361 h.flash(_('Token mismatch'), category='error')
362 h.flash(_('Token mismatch'), category='error')
362 return redirect(url('edit_repo', repo_name=repo_name))
363 return redirect(url('edit_repo', repo_name=repo_name))
363
364
364 @HasPermissionAllDecorator('hg.admin')
365 @HasPermissionAllDecorator('hg.admin')
365 def repo_pull(self, repo_name):
366 def repo_pull(self, repo_name):
366 """
367 """
367 Runs task to update given repository with remote changes,
368 Runs task to update given repository with remote changes,
368 ie. make pull on remote location
369 ie. make pull on remote location
369
370
370 :param repo_name:
371 :param repo_name:
371 """
372 """
372 try:
373 try:
373 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
374 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
374 h.flash(_('Pulled from remote location'), category='success')
375 h.flash(_('Pulled from remote location'), category='success')
375 except Exception, e:
376 except Exception, e:
376 h.flash(_('An error occurred during pull from remote location'),
377 h.flash(_('An error occurred during pull from remote location'),
377 category='error')
378 category='error')
378
379
379 return redirect(url('edit_repo', repo_name=repo_name))
380 return redirect(url('edit_repo', repo_name=repo_name))
380
381
381 @HasPermissionAllDecorator('hg.admin')
382 @HasPermissionAllDecorator('hg.admin')
382 def show(self, repo_name, format='html'):
383 def show(self, repo_name, format='html'):
383 """GET /repos/repo_name: Show a specific item"""
384 """GET /repos/repo_name: Show a specific item"""
384 # url('repo', repo_name=ID)
385 # url('repo', repo_name=ID)
385
386
386 @HasPermissionAllDecorator('hg.admin')
387 @HasPermissionAllDecorator('hg.admin')
387 def edit(self, repo_name, format='html'):
388 def edit(self, repo_name, format='html'):
388 """GET /repos/repo_name/edit: Form to edit an existing item"""
389 """GET /repos/repo_name/edit: Form to edit an existing item"""
389 # url('edit_repo', repo_name=ID)
390 # url('edit_repo', repo_name=ID)
390 defaults = self.__load_data(repo_name)
391 defaults = self.__load_data(repo_name)
391
392
392 return htmlfill.render(
393 return htmlfill.render(
393 render('admin/repos/repo_edit.html'),
394 render('admin/repos/repo_edit.html'),
394 defaults=defaults,
395 defaults=defaults,
395 encoding="UTF-8",
396 encoding="UTF-8",
396 force_defaults=False
397 force_defaults=False
397 )
398 )
General Comments 0
You need to be logged in to leave comments. Login now