##// END OF EJS Templates
fixed error for empty revisions on admin repo edit
marcink -
r711:cda88b3e beta
parent child Browse files
Show More
@@ -1,288 +1,290
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # repos controller for pylons
3 # repos controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 7, 2010
21 Created on April 7, 2010
22 admin controller for pylons
22 admin controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from formencode import htmlfill
25 from formencode import htmlfill
26 from operator import itemgetter
26 from operator import itemgetter
27 from paste.httpexceptions import HTTPInternalServerError
27 from paste.httpexceptions import HTTPInternalServerError
28 from pylons import request, response, session, tmpl_context as c, url
28 from pylons import request, response, session, tmpl_context as c, url
29 from pylons.controllers.util import abort, redirect
29 from pylons.controllers.util import abort, redirect
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31 from rhodecode.lib import helpers as h
31 from rhodecode.lib import helpers as h
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
33 HasPermissionAnyDecorator
33 HasPermissionAnyDecorator
34 from rhodecode.lib.base import BaseController, render
34 from rhodecode.lib.base import BaseController, render
35 from rhodecode.lib.utils import invalidate_cache, action_logger
35 from rhodecode.lib.utils import invalidate_cache, action_logger
36 from rhodecode.model.db import User
36 from rhodecode.model.db import User
37 from rhodecode.model.forms import RepoForm
37 from rhodecode.model.forms import RepoForm
38 from rhodecode.model.scm import ScmModel
38 from rhodecode.model.scm import ScmModel
39 from rhodecode.model.repo import RepoModel
39 from rhodecode.model.repo import RepoModel
40 import formencode
40 import formencode
41 import logging
41 import logging
42 import traceback
42 import traceback
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46 class ReposController(BaseController):
46 class ReposController(BaseController):
47 """REST Controller styled on the Atom Publishing Protocol"""
47 """REST Controller styled on the Atom Publishing Protocol"""
48 # To properly map this controller, ensure your config/routing.py
48 # To properly map this controller, ensure your config/routing.py
49 # file has a resource setup:
49 # file has a resource setup:
50 # map.resource('repo', 'repos')
50 # map.resource('repo', 'repos')
51
51
52 @LoginRequired()
52 @LoginRequired()
53 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
53 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
54 def __before__(self):
54 def __before__(self):
55 c.admin_user = session.get('admin_user')
55 c.admin_user = session.get('admin_user')
56 c.admin_username = session.get('admin_username')
56 c.admin_username = session.get('admin_username')
57 super(ReposController, self).__before__()
57 super(ReposController, self).__before__()
58
58
59 @HasPermissionAllDecorator('hg.admin')
59 @HasPermissionAllDecorator('hg.admin')
60 def index(self, format='html'):
60 def index(self, format='html'):
61 """GET /repos: All items in the collection"""
61 """GET /repos: All items in the collection"""
62 # url('repos')
62 # url('repos')
63 cached_repo_list = ScmModel().get_repos()
63 cached_repo_list = ScmModel().get_repos()
64 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
64 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
65 return render('admin/repos/repos.html')
65 return render('admin/repos/repos.html')
66
66
67 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
67 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
68 def create(self):
68 def create(self):
69 """POST /repos: Create a new item"""
69 """POST /repos: Create a new item"""
70 # url('repos')
70 # url('repos')
71 repo_model = RepoModel()
71 repo_model = RepoModel()
72 _form = RepoForm()()
72 _form = RepoForm()()
73 form_result = {}
73 form_result = {}
74 try:
74 try:
75 form_result = _form.to_python(dict(request.POST))
75 form_result = _form.to_python(dict(request.POST))
76 repo_model.create(form_result, c.rhodecode_user)
76 repo_model.create(form_result, c.rhodecode_user)
77 h.flash(_('created repository %s') % form_result['repo_name'],
77 h.flash(_('created repository %s') % form_result['repo_name'],
78 category='success')
78 category='success')
79
79
80 if request.POST.get('user_created'):
80 if request.POST.get('user_created'):
81 action_logger(self.rhodecode_user, 'user_created_repo',
81 action_logger(self.rhodecode_user, 'user_created_repo',
82 form_result['repo_name'], '', self.sa)
82 form_result['repo_name'], '', self.sa)
83 else:
83 else:
84 action_logger(self.rhodecode_user, 'admin_created_repo',
84 action_logger(self.rhodecode_user, 'admin_created_repo',
85 form_result['repo_name'], '', self.sa)
85 form_result['repo_name'], '', self.sa)
86
86
87 except formencode.Invalid, errors:
87 except formencode.Invalid, errors:
88 c.new_repo = errors.value['repo_name']
88 c.new_repo = errors.value['repo_name']
89
89
90 if request.POST.get('user_created'):
90 if request.POST.get('user_created'):
91 r = render('admin/repos/repo_add_create_repository.html')
91 r = render('admin/repos/repo_add_create_repository.html')
92 else:
92 else:
93 r = render('admin/repos/repo_add.html')
93 r = render('admin/repos/repo_add.html')
94
94
95 return htmlfill.render(
95 return htmlfill.render(
96 r,
96 r,
97 defaults=errors.value,
97 defaults=errors.value,
98 errors=errors.error_dict or {},
98 errors=errors.error_dict or {},
99 prefix_error=False,
99 prefix_error=False,
100 encoding="UTF-8")
100 encoding="UTF-8")
101
101
102 except Exception:
102 except Exception:
103 log.error(traceback.format_exc())
103 log.error(traceback.format_exc())
104 msg = _('error occured during creation of repository %s') \
104 msg = _('error occured during creation of repository %s') \
105 % form_result.get('repo_name')
105 % form_result.get('repo_name')
106 h.flash(msg, category='error')
106 h.flash(msg, category='error')
107 if request.POST.get('user_created'):
107 if request.POST.get('user_created'):
108 return redirect(url('home'))
108 return redirect(url('home'))
109 return redirect(url('repos'))
109 return redirect(url('repos'))
110
110
111 @HasPermissionAllDecorator('hg.admin')
111 @HasPermissionAllDecorator('hg.admin')
112 def new(self, format='html'):
112 def new(self, format='html'):
113 """GET /repos/new: Form to create a new item"""
113 """GET /repos/new: Form to create a new item"""
114 new_repo = request.GET.get('repo', '')
114 new_repo = request.GET.get('repo', '')
115 c.new_repo = h.repo_name_slug(new_repo)
115 c.new_repo = h.repo_name_slug(new_repo)
116
116
117 return render('admin/repos/repo_add.html')
117 return render('admin/repos/repo_add.html')
118
118
119 @HasPermissionAllDecorator('hg.admin')
119 @HasPermissionAllDecorator('hg.admin')
120 def update(self, repo_name):
120 def update(self, repo_name):
121 """PUT /repos/repo_name: Update an existing item"""
121 """PUT /repos/repo_name: Update an existing item"""
122 # Forms posted to this method should contain a hidden field:
122 # Forms posted to this method should contain a hidden field:
123 # <input type="hidden" name="_method" value="PUT" />
123 # <input type="hidden" name="_method" value="PUT" />
124 # Or using helpers:
124 # Or using helpers:
125 # h.form(url('repo', repo_name=ID),
125 # h.form(url('repo', repo_name=ID),
126 # method='put')
126 # method='put')
127 # url('repo', repo_name=ID)
127 # url('repo', repo_name=ID)
128 repo_model = RepoModel()
128 repo_model = RepoModel()
129 changed_name = repo_name
129 changed_name = repo_name
130 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
130 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
131
131
132 try:
132 try:
133 form_result = _form.to_python(dict(request.POST))
133 form_result = _form.to_python(dict(request.POST))
134 repo_model.update(repo_name, form_result)
134 repo_model.update(repo_name, form_result)
135 invalidate_cache('get_repo_cached_%s' % repo_name)
135 invalidate_cache('get_repo_cached_%s' % repo_name)
136 h.flash(_('Repository %s updated successfully' % repo_name),
136 h.flash(_('Repository %s updated successfully' % repo_name),
137 category='success')
137 category='success')
138 changed_name = form_result['repo_name']
138 changed_name = form_result['repo_name']
139 action_logger(self.rhodecode_user, 'admin_updated_repo',
139 action_logger(self.rhodecode_user, 'admin_updated_repo',
140 changed_name, '', self.sa)
140 changed_name, '', self.sa)
141
141
142 except formencode.Invalid, errors:
142 except formencode.Invalid, errors:
143 c.repo_info = repo_model.get(repo_name)
143 c.repo_info = repo_model.get(repo_name)
144 c.users_array = repo_model.get_users_js()
144 c.users_array = repo_model.get_users_js()
145 errors.value.update({'user':c.repo_info.user.username})
145 errors.value.update({'user':c.repo_info.user.username})
146 return htmlfill.render(
146 return htmlfill.render(
147 render('admin/repos/repo_edit.html'),
147 render('admin/repos/repo_edit.html'),
148 defaults=errors.value,
148 defaults=errors.value,
149 errors=errors.error_dict or {},
149 errors=errors.error_dict or {},
150 prefix_error=False,
150 prefix_error=False,
151 encoding="UTF-8")
151 encoding="UTF-8")
152
152
153 except Exception:
153 except Exception:
154 log.error(traceback.format_exc())
154 log.error(traceback.format_exc())
155 h.flash(_('error occurred during update of repository %s') \
155 h.flash(_('error occurred during update of repository %s') \
156 % repo_name, category='error')
156 % repo_name, category='error')
157
157
158 return redirect(url('edit_repo', repo_name=changed_name))
158 return redirect(url('edit_repo', repo_name=changed_name))
159
159
160 @HasPermissionAllDecorator('hg.admin')
160 @HasPermissionAllDecorator('hg.admin')
161 def delete(self, repo_name):
161 def delete(self, repo_name):
162 """DELETE /repos/repo_name: Delete an existing item"""
162 """DELETE /repos/repo_name: Delete an existing item"""
163 # Forms posted to this method should contain a hidden field:
163 # Forms posted to this method should contain a hidden field:
164 # <input type="hidden" name="_method" value="DELETE" />
164 # <input type="hidden" name="_method" value="DELETE" />
165 # Or using helpers:
165 # Or using helpers:
166 # h.form(url('repo', repo_name=ID),
166 # h.form(url('repo', repo_name=ID),
167 # method='delete')
167 # method='delete')
168 # url('repo', repo_name=ID)
168 # url('repo', repo_name=ID)
169
169
170 repo_model = RepoModel()
170 repo_model = RepoModel()
171 repo = repo_model.get(repo_name)
171 repo = repo_model.get(repo_name)
172 if not repo:
172 if not repo:
173 h.flash(_('%s repository is not mapped to db perhaps'
173 h.flash(_('%s repository is not mapped to db perhaps'
174 ' it was moved or renamed from the filesystem'
174 ' it was moved or renamed from the filesystem'
175 ' please run the application again'
175 ' please run the application again'
176 ' in order to rescan repositories') % repo_name,
176 ' in order to rescan repositories') % repo_name,
177 category='error')
177 category='error')
178
178
179 return redirect(url('repos'))
179 return redirect(url('repos'))
180 try:
180 try:
181 action_logger(self.rhodecode_user, 'admin_deleted_repo',
181 action_logger(self.rhodecode_user, 'admin_deleted_repo',
182 repo_name, '', self.sa)
182 repo_name, '', self.sa)
183 repo_model.delete(repo)
183 repo_model.delete(repo)
184 invalidate_cache('get_repo_cached_%s' % repo_name)
184 invalidate_cache('get_repo_cached_%s' % repo_name)
185 h.flash(_('deleted repository %s') % repo_name, category='success')
185 h.flash(_('deleted repository %s') % repo_name, category='success')
186
186
187 except Exception, e:
187 except Exception, e:
188 log.error(traceback.format_exc())
188 log.error(traceback.format_exc())
189 h.flash(_('An error occured during deletion of %s') % repo_name,
189 h.flash(_('An error occured during deletion of %s') % repo_name,
190 category='error')
190 category='error')
191
191
192 return redirect(url('repos'))
192 return redirect(url('repos'))
193
193
194 @HasPermissionAllDecorator('hg.admin')
194 @HasPermissionAllDecorator('hg.admin')
195 def delete_perm_user(self, repo_name):
195 def delete_perm_user(self, repo_name):
196 """
196 """
197 DELETE an existing repository permission user
197 DELETE an existing repository permission user
198 :param repo_name:
198 :param repo_name:
199 """
199 """
200
200
201 try:
201 try:
202 repo_model = RepoModel()
202 repo_model = RepoModel()
203 repo_model.delete_perm_user(request.POST, repo_name)
203 repo_model.delete_perm_user(request.POST, repo_name)
204 except Exception, e:
204 except Exception, e:
205 h.flash(_('An error occured during deletion of repository user'),
205 h.flash(_('An error occured during deletion of repository user'),
206 category='error')
206 category='error')
207 raise HTTPInternalServerError()
207 raise HTTPInternalServerError()
208
208
209 @HasPermissionAllDecorator('hg.admin')
209 @HasPermissionAllDecorator('hg.admin')
210 def repo_stats(self, repo_name):
210 def repo_stats(self, repo_name):
211 """
211 """
212 DELETE an existing repository statistics
212 DELETE an existing repository statistics
213 :param repo_name:
213 :param repo_name:
214 """
214 """
215
215
216 try:
216 try:
217 repo_model = RepoModel()
217 repo_model = RepoModel()
218 repo_model.delete_stats(repo_name)
218 repo_model.delete_stats(repo_name)
219 except Exception, e:
219 except Exception, e:
220 h.flash(_('An error occured during deletion of repository stats'),
220 h.flash(_('An error occured during deletion of repository stats'),
221 category='error')
221 category='error')
222 return redirect(url('edit_repo', repo_name=repo_name))
222 return redirect(url('edit_repo', repo_name=repo_name))
223
223
224 @HasPermissionAllDecorator('hg.admin')
224 @HasPermissionAllDecorator('hg.admin')
225 def repo_cache(self, repo_name):
225 def repo_cache(self, repo_name):
226 """
226 """
227 INVALIDATE exisitings repository cache
227 INVALIDATE exisitings repository cache
228 :param repo_name:
228 :param repo_name:
229 """
229 """
230
230
231 try:
231 try:
232 ScmModel().mark_for_invalidation(repo_name)
232 ScmModel().mark_for_invalidation(repo_name)
233 except Exception, e:
233 except Exception, e:
234 h.flash(_('An error occured during cache invalidation'),
234 h.flash(_('An error occurred during cache invalidation'),
235 category='error')
235 category='error')
236 return redirect(url('edit_repo', repo_name=repo_name))
236 return redirect(url('edit_repo', repo_name=repo_name))
237
237
238 @HasPermissionAllDecorator('hg.admin')
238 @HasPermissionAllDecorator('hg.admin')
239 def show(self, repo_name, format='html'):
239 def show(self, repo_name, format='html'):
240 """GET /repos/repo_name: Show a specific item"""
240 """GET /repos/repo_name: Show a specific item"""
241 # url('repo', repo_name=ID)
241 # url('repo', repo_name=ID)
242
242
243 @HasPermissionAllDecorator('hg.admin')
243 @HasPermissionAllDecorator('hg.admin')
244 def edit(self, repo_name, format='html'):
244 def edit(self, repo_name, format='html'):
245 """GET /repos/repo_name/edit: Form to edit an existing item"""
245 """GET /repos/repo_name/edit: Form to edit an existing item"""
246 # url('edit_repo', repo_name=ID)
246 # url('edit_repo', repo_name=ID)
247 repo_model = RepoModel()
247 repo_model = RepoModel()
248 c.repo_info = repo = repo_model.get(repo_name)
248 c.repo_info = repo = repo_model.get(repo_name)
249 if repo.stats:
249 if repo.stats:
250 last_rev = repo.stats.stat_on_revision
250 last_rev = repo.stats.stat_on_revision
251 else:
251 else:
252 last_rev = 0
252 last_rev = 0
253 c.stats_revision = last_rev
253 c.stats_revision = last_rev
254 c.repo_last_rev = ScmModel().get(repo_name).revisions[-1]
254 r = ScmModel().get(repo_name)
255 c.repo_last_rev = r.revisions[-1] if r.revisions else 0
256
255 if last_rev == 0:
257 if last_rev == 0:
256 c.stats_percentage = 0
258 c.stats_percentage = 0
257 else:
259 else:
258 c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100)
260 c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100)
259
261
260
262
261 if not repo:
263 if not repo:
262 h.flash(_('%s repository is not mapped to db perhaps'
264 h.flash(_('%s repository is not mapped to db perhaps'
263 ' it was created or renamed from the filesystem'
265 ' it was created or renamed from the filesystem'
264 ' please run the application again'
266 ' please run the application again'
265 ' in order to rescan repositories') % repo_name,
267 ' in order to rescan repositories') % repo_name,
266 category='error')
268 category='error')
267
269
268 return redirect(url('repos'))
270 return redirect(url('repos'))
269 defaults = c.repo_info.__dict__
271 defaults = c.repo_info.__dict__
270 if c.repo_info.user:
272 if c.repo_info.user:
271 defaults.update({'user':c.repo_info.user.username})
273 defaults.update({'user':c.repo_info.user.username})
272 else:
274 else:
273 replacement_user = self.sa.query(User)\
275 replacement_user = self.sa.query(User)\
274 .filter(User.admin == True).first().username
276 .filter(User.admin == True).first().username
275 defaults.update({'user':replacement_user})
277 defaults.update({'user':replacement_user})
276
278
277 c.users_array = repo_model.get_users_js()
279 c.users_array = repo_model.get_users_js()
278
280
279 for p in c.repo_info.repo_to_perm:
281 for p in c.repo_info.repo_to_perm:
280 defaults.update({'perm_%s' % p.user.username:
282 defaults.update({'perm_%s' % p.user.username:
281 p.permission.permission_name})
283 p.permission.permission_name})
282
284
283 return htmlfill.render(
285 return htmlfill.render(
284 render('admin/repos/repo_edit.html'),
286 render('admin/repos/repo_edit.html'),
285 defaults=defaults,
287 defaults=defaults,
286 encoding="UTF-8",
288 encoding="UTF-8",
287 force_defaults=False
289 force_defaults=False
288 )
290 )
General Comments 0
You need to be logged in to leave comments. Login now