##// END OF EJS Templates
merge
marcink -
r830:e46d25e5 merge beta
parent child Browse files
Show More
@@ -1,312 +1,313 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.repos
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Admin controller for RhodeCode
7 7
8 8 :created_on: Apr 7, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27
28 28 import logging
29 29 import traceback
30 30 import formencode
31 31 from operator import itemgetter
32 32 from formencode import htmlfill
33 33
34 34 from paste.httpexceptions import HTTPInternalServerError
35 35 from pylons import request, response, session, tmpl_context as c, url
36 36 from pylons.controllers.util import abort, redirect
37 37 from pylons.i18n.translation import _
38 38
39 39 from rhodecode.lib import helpers as h
40 40 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
41 41 HasPermissionAnyDecorator
42 42 from rhodecode.lib.base import BaseController, render
43 43 from rhodecode.lib.utils import invalidate_cache, action_logger
44 44 from rhodecode.model.db import User
45 45 from rhodecode.model.forms import RepoForm
46 46 from rhodecode.model.scm import ScmModel
47 47 from rhodecode.model.repo import RepoModel
48 48
49 49
50 50 log = logging.getLogger(__name__)
51 51
52 52 class ReposController(BaseController):
53 53 """REST Controller styled on the Atom Publishing Protocol"""
54 54 # To properly map this controller, ensure your config/routing.py
55 55 # file has a resource setup:
56 56 # map.resource('repo', 'repos')
57 57
58 58 @LoginRequired()
59 59 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
60 60 def __before__(self):
61 61 c.admin_user = session.get('admin_user')
62 62 c.admin_username = session.get('admin_username')
63 63 super(ReposController, self).__before__()
64 64
65 65 @HasPermissionAllDecorator('hg.admin')
66 66 def index(self, format='html'):
67 67 """GET /repos: All items in the collection"""
68 68 # url('repos')
69 69 cached_repo_list = ScmModel().get_repos()
70 70 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
71 71 return render('admin/repos/repos.html')
72 72
73 73 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
74 74 def create(self):
75 75 """POST /repos: Create a new item"""
76 76 # url('repos')
77 77 repo_model = RepoModel()
78 78 _form = RepoForm()()
79 79 form_result = {}
80 80 try:
81 81 form_result = _form.to_python(dict(request.POST))
82 82 repo_model.create(form_result, c.rhodecode_user)
83 83 h.flash(_('created repository %s') % form_result['repo_name'],
84 84 category='success')
85 85
86 86 if request.POST.get('user_created'):
87 87 action_logger(self.rhodecode_user, 'user_created_repo',
88 88 form_result['repo_name'], '', self.sa)
89 89 else:
90 90 action_logger(self.rhodecode_user, 'admin_created_repo',
91 91 form_result['repo_name'], '', self.sa)
92 92
93 93 except formencode.Invalid, errors:
94 94 c.new_repo = errors.value['repo_name']
95 95
96 96 if request.POST.get('user_created'):
97 97 r = render('admin/repos/repo_add_create_repository.html')
98 98 else:
99 99 r = render('admin/repos/repo_add.html')
100 100
101 101 return htmlfill.render(
102 102 r,
103 103 defaults=errors.value,
104 104 errors=errors.error_dict or {},
105 105 prefix_error=False,
106 106 encoding="UTF-8")
107 107
108 108 except Exception:
109 109 log.error(traceback.format_exc())
110 110 msg = _('error occured during creation of repository %s') \
111 111 % form_result.get('repo_name')
112 112 h.flash(msg, category='error')
113 113 if request.POST.get('user_created'):
114 114 return redirect(url('home'))
115 115 return redirect(url('repos'))
116 116
117 117 @HasPermissionAllDecorator('hg.admin')
118 118 def new(self, format='html'):
119 119 """GET /repos/new: Form to create a new item"""
120 120 new_repo = request.GET.get('repo', '')
121 121 c.new_repo = h.repo_name_slug(new_repo)
122 122
123 123 return render('admin/repos/repo_add.html')
124 124
125 125 @HasPermissionAllDecorator('hg.admin')
126 126 def update(self, repo_name):
127 127 """PUT /repos/repo_name: Update an existing item"""
128 128 # Forms posted to this method should contain a hidden field:
129 129 # <input type="hidden" name="_method" value="PUT" />
130 130 # Or using helpers:
131 131 # h.form(url('repo', repo_name=ID),
132 132 # method='put')
133 133 # url('repo', repo_name=ID)
134 134 repo_model = RepoModel()
135 135 changed_name = repo_name
136 136 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
137 137
138 138 try:
139 139 form_result = _form.to_python(dict(request.POST))
140 140 repo_model.update(repo_name, form_result)
141 141 invalidate_cache('get_repo_cached_%s' % repo_name)
142 142 h.flash(_('Repository %s updated successfully' % repo_name),
143 143 category='success')
144 144 changed_name = form_result['repo_name']
145 145 action_logger(self.rhodecode_user, 'admin_updated_repo',
146 146 changed_name, '', self.sa)
147 147
148 148 except formencode.Invalid, errors:
149 149 c.repo_info = repo_model.get_by_repo_name(repo_name)
150 150 if c.repo_info.stats:
151 151 last_rev = c.repo_info.stats.stat_on_revision
152 152 else:
153 153 last_rev = 0
154 154 c.stats_revision = last_rev
155 155 r = ScmModel().get(repo_name)
156 156 c.repo_last_rev = r.revisions[-1] if r.revisions else 0
157 157
158 158 if last_rev == 0:
159 159 c.stats_percentage = 0
160 160 else:
161 161 c.stats_percentage = '%.2f' % ((float((last_rev)) /
162 162 c.repo_last_rev) * 100)
163 163
164 164 c.users_array = repo_model.get_users_js()
165 165 errors.value.update({'user':c.repo_info.user.username})
166 166 return htmlfill.render(
167 167 render('admin/repos/repo_edit.html'),
168 168 defaults=errors.value,
169 169 errors=errors.error_dict or {},
170 170 prefix_error=False,
171 171 encoding="UTF-8")
172 172
173 173 except Exception:
174 174 log.error(traceback.format_exc())
175 175 h.flash(_('error occurred during update of repository %s') \
176 176 % repo_name, category='error')
177 177
178 178 return redirect(url('edit_repo', repo_name=changed_name))
179 179
180 180 @HasPermissionAllDecorator('hg.admin')
181 181 def delete(self, repo_name):
182 182 """DELETE /repos/repo_name: Delete an existing item"""
183 183 # Forms posted to this method should contain a hidden field:
184 184 # <input type="hidden" name="_method" value="DELETE" />
185 185 # Or using helpers:
186 186 # h.form(url('repo', repo_name=ID),
187 187 # method='delete')
188 188 # url('repo', repo_name=ID)
189 189
190 190 repo_model = RepoModel()
191 191 repo = repo_model.get_by_repo_name(repo_name)
192 192 if not repo:
193 193 h.flash(_('%s repository is not mapped to db perhaps'
194 194 ' it was moved or renamed from the filesystem'
195 195 ' please run the application again'
196 196 ' in order to rescan repositories') % repo_name,
197 197 category='error')
198 198
199 199 return redirect(url('repos'))
200 200 try:
201 201 action_logger(self.rhodecode_user, 'admin_deleted_repo',
202 202 repo_name, '', self.sa)
203 203 repo_model.delete(repo)
204 204 invalidate_cache('get_repo_cached_%s' % repo_name)
205 205 h.flash(_('deleted repository %s') % repo_name, category='success')
206 206
207 207 except Exception, e:
208 208 log.error(traceback.format_exc())
209 209 h.flash(_('An error occured during deletion of %s') % repo_name,
210 210 category='error')
211 211
212 212 return redirect(url('repos'))
213 213
214 214 @HasPermissionAllDecorator('hg.admin')
215 215 def delete_perm_user(self, repo_name):
216 216 """
217 217 DELETE an existing repository permission user
218 218 :param repo_name:
219 219 """
220 220
221 221 try:
222 222 repo_model = RepoModel()
223 223 repo_model.delete_perm_user(request.POST, repo_name)
224 224 except Exception, e:
225 225 h.flash(_('An error occured during deletion of repository user'),
226 226 category='error')
227 227 raise HTTPInternalServerError()
228 228
229 229 @HasPermissionAllDecorator('hg.admin')
230 230 def repo_stats(self, repo_name):
231 231 """
232 232 DELETE an existing repository statistics
233 233 :param repo_name:
234 234 """
235 235
236 236 try:
237 237 repo_model = RepoModel()
238 238 repo_model.delete_stats(repo_name)
239 239 except Exception, e:
240 240 h.flash(_('An error occured during deletion of repository stats'),
241 241 category='error')
242 242 return redirect(url('edit_repo', repo_name=repo_name))
243 243
244 244 @HasPermissionAllDecorator('hg.admin')
245 245 def repo_cache(self, repo_name):
246 246 """
247 247 INVALIDATE exisitings repository cache
248 248 :param repo_name:
249 249 """
250 250
251 251 try:
252 252 ScmModel().mark_for_invalidation(repo_name)
253 253 except Exception, e:
254 254 h.flash(_('An error occurred during cache invalidation'),
255 255 category='error')
256 256 return redirect(url('edit_repo', repo_name=repo_name))
257 257
258 258 @HasPermissionAllDecorator('hg.admin')
259 259 def show(self, repo_name, format='html'):
260 260 """GET /repos/repo_name: Show a specific item"""
261 261 # url('repo', repo_name=ID)
262 262
263 263 @HasPermissionAllDecorator('hg.admin')
264 264 def edit(self, repo_name, format='html'):
265 265 """GET /repos/repo_name/edit: Form to edit an existing item"""
266 266 # url('edit_repo', repo_name=ID)
267 267 repo_model = RepoModel()
268 268 c.repo_info = repo_model.get_by_repo_name(repo_name)
269 r = ScmModel().get(repo_name)
270
269 271 if c.repo_info.stats:
270 272 last_rev = c.repo_info.stats.stat_on_revision
271 273 else:
272 274 last_rev = 0
273 275 c.stats_revision = last_rev
274 r = ScmModel().get(repo_name)
276
275 277 c.repo_last_rev = r.revisions[-1] if r.revisions else 0
276 278
277 279 if last_rev == 0:
278 280 c.stats_percentage = 0
279 281 else:
280 282 c.stats_percentage = '%.2f' % ((float((last_rev)) /
281 283 c.repo_last_rev) * 100)
282 284
283
284 285 if not c.repo_info:
285 286 h.flash(_('%s repository is not mapped to db perhaps'
286 287 ' it was created or renamed from the filesystem'
287 288 ' please run the application again'
288 289 ' in order to rescan repositories') % repo_name,
289 290 category='error')
290 291
291 292 return redirect(url('repos'))
292 293
293 defaults = c.repo_info.__dict__
294 defaults = c.repo_info.__dict__.copy()
294 295 if c.repo_info.user:
295 296 defaults.update({'user':c.repo_info.user.username})
296 297 else:
297 298 replacement_user = self.sa.query(User)\
298 299 .filter(User.admin == True).first().username
299 300 defaults.update({'user':replacement_user})
300 301
301 302 c.users_array = repo_model.get_users_js()
302 303
303 304 for p in c.repo_info.repo_to_perm:
304 305 defaults.update({'perm_%s' % p.user.username:
305 306 p.permission.permission_name})
306 307
307 308 return htmlfill.render(
308 309 render('admin/repos/repo_edit.html'),
309 310 defaults=defaults,
310 311 encoding="UTF-8",
311 312 force_defaults=False
312 313 )
@@ -1,339 +1,339 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 package.rhodecode.controllers.admin.settings
4 4 ~~~~~~~~~~~~~~
5 5 settings controller for rhodecode admin
6 6
7 7 :created_on: Jul 14, 2010
8 8 :author: marcink
9 9 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 10 :license: GPLv3, see COPYING for more details.
11 11 """
12 12 # This program is free software; you can redistribute it and/or
13 13 # modify it under the terms of the GNU General Public License
14 14 # as published by the Free Software Foundation; version 2
15 15 # of the License or (at your opinion) any later version of the license.
16 16 #
17 17 # This program is distributed in the hope that it will be useful,
18 18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 20 # GNU General Public License for more details.
21 21 #
22 22 # You should have received a copy of the GNU General Public License
23 23 # along with this program; if not, write to the Free Software
24 24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 25 # MA 02110-1301, USA.
26 26
27 27 from formencode import htmlfill
28 28 from pylons import request, session, tmpl_context as c, url, app_globals as g, \
29 29 config
30 30 from pylons.controllers.util import abort, redirect
31 31 from pylons.i18n.translation import _
32 32 from rhodecode.lib import helpers as h
33 33 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
34 34 HasPermissionAnyDecorator, NotAnonymous
35 35 from rhodecode.lib.base import BaseController, render
36 36 from rhodecode.lib.celerylib import tasks, run_task
37 37 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
38 38 set_rhodecode_config
39 39 from rhodecode.model.db import RhodeCodeUi, Repository
40 40 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
41 41 ApplicationUiSettingsForm
42 42 from rhodecode.model.scm import ScmModel
43 43 from rhodecode.model.settings import SettingsModel
44 44 from rhodecode.model.user import UserModel
45 45 from sqlalchemy import func
46 46 import formencode
47 47 import logging
48 48 import traceback
49 49
50 50 log = logging.getLogger(__name__)
51 51
52 52
53 53 class SettingsController(BaseController):
54 54 """REST Controller styled on the Atom Publishing Protocol"""
55 55 # To properly map this controller, ensure your config/routing.py
56 56 # file has a resource setup:
57 57 # map.resource('setting', 'settings', controller='admin/settings',
58 58 # path_prefix='/admin', name_prefix='admin_')
59 59
60 60
61 61 @LoginRequired()
62 62 def __before__(self):
63 63 c.admin_user = session.get('admin_user')
64 64 c.admin_username = session.get('admin_username')
65 65 super(SettingsController, self).__before__()
66 66
67 67
68 68 @HasPermissionAllDecorator('hg.admin')
69 69 def index(self, format='html'):
70 70 """GET /admin/settings: All items in the collection"""
71 71 # url('admin_settings')
72 72
73 73 defaults = SettingsModel().get_app_settings()
74 74 defaults.update(self.get_hg_ui_settings())
75 75 return htmlfill.render(
76 76 render('admin/settings/settings.html'),
77 77 defaults=defaults,
78 78 encoding="UTF-8",
79 79 force_defaults=False
80 80 )
81 81
82 82 @HasPermissionAllDecorator('hg.admin')
83 83 def create(self):
84 84 """POST /admin/settings: Create a new item"""
85 85 # url('admin_settings')
86 86
87 87 @HasPermissionAllDecorator('hg.admin')
88 88 def new(self, format='html'):
89 89 """GET /admin/settings/new: Form to create a new item"""
90 90 # url('admin_new_setting')
91 91
92 92 @HasPermissionAllDecorator('hg.admin')
93 93 def update(self, setting_id):
94 94 """PUT /admin/settings/setting_id: Update an existing item"""
95 95 # Forms posted to this method should contain a hidden field:
96 96 # <input type="hidden" name="_method" value="PUT" />
97 97 # Or using helpers:
98 98 # h.form(url('admin_setting', setting_id=ID),
99 99 # method='put')
100 100 # url('admin_setting', setting_id=ID)
101 101 if setting_id == 'mapping':
102 102 rm_obsolete = request.POST.get('destroy', False)
103 103 log.debug('Rescanning directories with destroy=%s', rm_obsolete)
104 104
105 105 initial = ScmModel().repo_scan(g.paths[0][1], g.baseui)
106 106 for repo_name in initial.keys():
107 107 invalidate_cache('get_repo_cached_%s' % repo_name)
108 108
109 109 repo2db_mapper(initial, rm_obsolete)
110 110
111 111 h.flash(_('Repositories successfully rescanned'), category='success')
112 112
113 113 if setting_id == 'whoosh':
114 114 repo_location = self.get_hg_ui_settings()['paths_root_path']
115 115 full_index = request.POST.get('full_index', False)
116 116 task = run_task(tasks.whoosh_index, repo_location, full_index)
117 117
118 118 h.flash(_('Whoosh reindex task scheduled'), category='success')
119 119 if setting_id == 'global':
120 120
121 121 application_form = ApplicationSettingsForm()()
122 122 try:
123 123 form_result = application_form.to_python(dict(request.POST))
124 124 settings_model = SettingsModel()
125 125 try:
126 126 hgsettings1 = settings_model.get('title')
127 127 hgsettings1.app_settings_value = form_result['rhodecode_title']
128 128
129 129 hgsettings2 = settings_model.get('realm')
130 130 hgsettings2.app_settings_value = form_result['rhodecode_realm']
131 131
132 132
133 133 self.sa.add(hgsettings1)
134 134 self.sa.add(hgsettings2)
135 135 self.sa.commit()
136 136 set_rhodecode_config(config)
137 137 h.flash(_('Updated application settings'),
138 138 category='success')
139 139
140 140 except:
141 141 log.error(traceback.format_exc())
142 142 h.flash(_('error occurred during updating application settings'),
143 143 category='error')
144 144
145 145 self.sa.rollback()
146 146
147 147
148 148 except formencode.Invalid, errors:
149 149 return htmlfill.render(
150 150 render('admin/settings/settings.html'),
151 151 defaults=errors.value,
152 152 errors=errors.error_dict or {},
153 153 prefix_error=False,
154 154 encoding="UTF-8")
155 155
156 156 if setting_id == 'mercurial':
157 157 application_form = ApplicationUiSettingsForm()()
158 158 try:
159 159 form_result = application_form.to_python(dict(request.POST))
160 160
161 161 try:
162 162
163 163 hgsettings1 = self.sa.query(RhodeCodeUi)\
164 164 .filter(RhodeCodeUi.ui_key == 'push_ssl').one()
165 165 hgsettings1.ui_value = form_result['web_push_ssl']
166 166
167 167 hgsettings2 = self.sa.query(RhodeCodeUi)\
168 168 .filter(RhodeCodeUi.ui_key == '/').one()
169 169 hgsettings2.ui_value = form_result['paths_root_path']
170 170
171 171
172 172 #HOOKS
173 173 hgsettings3 = self.sa.query(RhodeCodeUi)\
174 174 .filter(RhodeCodeUi.ui_key == 'changegroup.update').one()
175 175 hgsettings3.ui_active = bool(form_result['hooks_changegroup_update'])
176 176
177 177 hgsettings4 = self.sa.query(RhodeCodeUi)\
178 178 .filter(RhodeCodeUi.ui_key == 'changegroup.repo_size').one()
179 179 hgsettings4.ui_active = bool(form_result['hooks_changegroup_repo_size'])
180 180
181 181 hgsettings5 = self.sa.query(RhodeCodeUi)\
182 182 .filter(RhodeCodeUi.ui_key == 'pretxnchangegroup.push_logger').one()
183 183 hgsettings5.ui_active = bool(form_result['hooks_pretxnchangegroup_push_logger'])
184 184
185 185 hgsettings6 = self.sa.query(RhodeCodeUi)\
186 186 .filter(RhodeCodeUi.ui_key == 'preoutgoing.pull_logger').one()
187 187 hgsettings6.ui_active = bool(form_result['hooks_preoutgoing_pull_logger'])
188 188
189 189
190 190 self.sa.add(hgsettings1)
191 191 self.sa.add(hgsettings2)
192 192 self.sa.add(hgsettings3)
193 193 self.sa.add(hgsettings4)
194 194 self.sa.add(hgsettings5)
195 195 self.sa.add(hgsettings6)
196 196 self.sa.commit()
197 197
198 198 h.flash(_('Updated mercurial settings'),
199 199 category='success')
200 200
201 201 except:
202 202 log.error(traceback.format_exc())
203 203 h.flash(_('error occurred during updating application settings'),
204 204 category='error')
205 205
206 206 self.sa.rollback()
207 207
208 208
209 209 except formencode.Invalid, errors:
210 210 return htmlfill.render(
211 211 render('admin/settings/settings.html'),
212 212 defaults=errors.value,
213 213 errors=errors.error_dict or {},
214 214 prefix_error=False,
215 215 encoding="UTF-8")
216 216
217 217
218 218
219 219 return redirect(url('admin_settings'))
220 220
221 221 @HasPermissionAllDecorator('hg.admin')
222 222 def delete(self, setting_id):
223 223 """DELETE /admin/settings/setting_id: Delete an existing item"""
224 224 # Forms posted to this method should contain a hidden field:
225 225 # <input type="hidden" name="_method" value="DELETE" />
226 226 # Or using helpers:
227 227 # h.form(url('admin_setting', setting_id=ID),
228 228 # method='delete')
229 229 # url('admin_setting', setting_id=ID)
230 230
231 231 @HasPermissionAllDecorator('hg.admin')
232 232 def show(self, setting_id, format='html'):
233 233 """GET /admin/settings/setting_id: Show a specific item"""
234 234 # url('admin_setting', setting_id=ID)
235 235
236 236 @HasPermissionAllDecorator('hg.admin')
237 237 def edit(self, setting_id, format='html'):
238 238 """GET /admin/settings/setting_id/edit: Form to edit an existing item"""
239 239 # url('admin_edit_setting', setting_id=ID)
240 240
241 241 @NotAnonymous()
242 242 def my_account(self):
243 243 """
244 244 GET /_admin/my_account Displays info about my account
245 245 """
246 246 # url('admin_settings_my_account')
247 247
248 248 c.user = UserModel().get(c.rhodecode_user.user_id, cache=False)
249 249 all_repos = self.sa.query(Repository)\
250 250 .filter(Repository.user_id == c.user.user_id)\
251 251 .order_by(func.lower(Repository.repo_name))\
252 252 .all()
253 253
254 254 c.user_repos = ScmModel().get_repos(all_repos)
255 255
256 256 if c.user.username == 'default':
257 257 h.flash(_("You can't edit this user since it's"
258 258 " crucial for entire application"), category='warning')
259 259 return redirect(url('users'))
260 260
261 defaults = c.user.__dict__
261 defaults = c.user.__dict__.copy()
262 262 return htmlfill.render(
263 263 render('admin/users/user_edit_my_account.html'),
264 264 defaults=defaults,
265 265 encoding="UTF-8",
266 266 force_defaults=False
267 267 )
268 268
269 269 def my_account_update(self):
270 270 """PUT /_admin/my_account_update: Update an existing item"""
271 271 # Forms posted to this method should contain a hidden field:
272 272 # <input type="hidden" name="_method" value="PUT" />
273 273 # Or using helpers:
274 274 # h.form(url('admin_settings_my_account_update'),
275 275 # method='put')
276 276 # url('admin_settings_my_account_update', id=ID)
277 277 user_model = UserModel()
278 278 uid = c.rhodecode_user.user_id
279 279 _form = UserForm(edit=True, old_data={'user_id':uid,
280 280 'email':c.rhodecode_user.email})()
281 281 form_result = {}
282 282 try:
283 283 form_result = _form.to_python(dict(request.POST))
284 284 user_model.update_my_account(uid, form_result)
285 285 h.flash(_('Your account was updated successfully'),
286 286 category='success')
287 287
288 288 except formencode.Invalid, errors:
289 289 c.user = user_model.get(c.rhodecode_user.user_id, cache=False)
290 290 c.user = UserModel().get(c.rhodecode_user.user_id, cache=False)
291 291 all_repos = self.sa.query(Repository)\
292 292 .filter(Repository.user_id == c.user.user_id)\
293 293 .order_by(func.lower(Repository.repo_name))\
294 294 .all()
295 295 c.user_repos = ScmModel().get_repos(all_repos)
296 296
297 297 return htmlfill.render(
298 298 render('admin/users/user_edit_my_account.html'),
299 299 defaults=errors.value,
300 300 errors=errors.error_dict or {},
301 301 prefix_error=False,
302 302 encoding="UTF-8")
303 303 except Exception:
304 304 log.error(traceback.format_exc())
305 305 h.flash(_('error occurred during update of user %s') \
306 306 % form_result.get('username'), category='error')
307 307
308 308 return redirect(url('my_account'))
309 309
310 310 @NotAnonymous()
311 311 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
312 312 def create_repository(self):
313 313 """GET /_admin/create_repository: Form to create a new item"""
314 314 new_repo = request.GET.get('repo', '')
315 315 c.new_repo = h.repo_name_slug(new_repo)
316 316
317 317 return render('admin/repos/repo_add_create_repository.html')
318 318
319 319 def get_hg_ui_settings(self):
320 320 ret = self.sa.query(RhodeCodeUi).all()
321 321
322 322 if not ret:
323 323 raise Exception('Could not get application ui settings !')
324 324 settings = {}
325 325 for each in ret:
326 326 k = each.ui_key
327 327 v = each.ui_value
328 328 if k == '/':
329 329 k = 'root_path'
330 330
331 331 if k.find('.') != -1:
332 332 k = k.replace('.', '_')
333 333
334 334 if each.ui_section == 'hooks':
335 335 v = each.ui_active
336 336
337 337 settings[each.ui_section + '_' + k] = v
338 338
339 339 return settings
@@ -1,167 +1,167 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # users controller for pylons
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 4, 2010
22 22 users controller for pylons
23 23 @author: marcink
24 24 """
25 25
26 26 from formencode import htmlfill
27 27 from pylons import request, session, tmpl_context as c, url
28 28 from pylons.controllers.util import abort, redirect
29 29 from pylons.i18n.translation import _
30 30 from rhodecode.lib.exceptions import *
31 31 from rhodecode.lib import helpers as h
32 32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
33 33 from rhodecode.lib.base import BaseController, render
34 34 from rhodecode.model.db import User
35 35 from rhodecode.model.forms import UserForm
36 36 from rhodecode.model.user import UserModel
37 37 import formencode
38 38 import logging
39 39 import traceback
40 40
41 41 log = logging.getLogger(__name__)
42 42
43 43 class UsersController(BaseController):
44 44 """REST Controller styled on the Atom Publishing Protocol"""
45 45 # To properly map this controller, ensure your config/routing.py
46 46 # file has a resource setup:
47 47 # map.resource('user', 'users')
48 48
49 49 @LoginRequired()
50 50 @HasPermissionAllDecorator('hg.admin')
51 51 def __before__(self):
52 52 c.admin_user = session.get('admin_user')
53 53 c.admin_username = session.get('admin_username')
54 54 super(UsersController, self).__before__()
55 55
56 56
57 57 def index(self, format='html'):
58 58 """GET /users: All items in the collection"""
59 59 # url('users')
60 60
61 61 c.users_list = self.sa.query(User).all()
62 62 return render('admin/users/users.html')
63 63
64 64 def create(self):
65 65 """POST /users: Create a new item"""
66 66 # url('users')
67 67
68 68 user_model = UserModel()
69 69 login_form = UserForm()()
70 70 try:
71 71 form_result = login_form.to_python(dict(request.POST))
72 72 user_model.create(form_result)
73 73 h.flash(_('created user %s') % form_result['username'],
74 74 category='success')
75 75 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
76 76 except formencode.Invalid, errors:
77 77 return htmlfill.render(
78 78 render('admin/users/user_add.html'),
79 79 defaults=errors.value,
80 80 errors=errors.error_dict or {},
81 81 prefix_error=False,
82 82 encoding="UTF-8")
83 83 except Exception:
84 84 log.error(traceback.format_exc())
85 85 h.flash(_('error occured during creation of user %s') \
86 86 % request.POST.get('username'), category='error')
87 87 return redirect(url('users'))
88 88
89 89 def new(self, format='html'):
90 90 """GET /users/new: Form to create a new item"""
91 91 # url('new_user')
92 92 return render('admin/users/user_add.html')
93 93
94 94 def update(self, id):
95 95 """PUT /users/id: Update an existing item"""
96 96 # Forms posted to this method should contain a hidden field:
97 97 # <input type="hidden" name="_method" value="PUT" />
98 98 # Or using helpers:
99 99 # h.form(url('user', id=ID),
100 100 # method='put')
101 101 # url('user', id=ID)
102 102 user_model = UserModel()
103 103 c.user = user_model.get(id)
104 104
105 105 _form = UserForm(edit=True, old_data={'user_id':id,
106 106 'email':c.user.email})()
107 107 form_result = {}
108 108 try:
109 109 form_result = _form.to_python(dict(request.POST))
110 110 user_model.update(id, form_result)
111 111 h.flash(_('User updated succesfully'), category='success')
112 112
113 113 except formencode.Invalid, errors:
114 114 return htmlfill.render(
115 115 render('admin/users/user_edit.html'),
116 116 defaults=errors.value,
117 117 errors=errors.error_dict or {},
118 118 prefix_error=False,
119 119 encoding="UTF-8")
120 120 except Exception:
121 121 log.error(traceback.format_exc())
122 122 h.flash(_('error occured during update of user %s') \
123 123 % form_result.get('username'), category='error')
124 124
125 125 return redirect(url('users'))
126 126
127 127 def delete(self, id):
128 128 """DELETE /users/id: Delete an existing item"""
129 129 # Forms posted to this method should contain a hidden field:
130 130 # <input type="hidden" name="_method" value="DELETE" />
131 131 # Or using helpers:
132 132 # h.form(url('user', id=ID),
133 133 # method='delete')
134 134 # url('user', id=ID)
135 135 user_model = UserModel()
136 136 try:
137 137 user_model.delete(id)
138 138 h.flash(_('sucessfully deleted user'), category='success')
139 139 except (UserOwnsReposException, DefaultUserException), e:
140 140 h.flash(str(e), category='warning')
141 141 except Exception:
142 142 h.flash(_('An error occured during deletion of user'),
143 143 category='error')
144 144 return redirect(url('users'))
145 145
146 146 def show(self, id, format='html'):
147 147 """GET /users/id: Show a specific item"""
148 148 # url('user', id=ID)
149 149
150 150
151 151 def edit(self, id, format='html'):
152 152 """GET /users/id/edit: Form to edit an existing item"""
153 153 # url('edit_user', id=ID)
154 154 c.user = self.sa.query(User).get(id)
155 155 if not c.user:
156 156 return redirect(url('users'))
157 157 if c.user.username == 'default':
158 158 h.flash(_("You can't edit this user"), category='warning')
159 159 return redirect(url('users'))
160 160
161 defaults = c.user.__dict__
161 defaults = c.user.__dict__.copy()
162 162 return htmlfill.render(
163 163 render('admin/users/user_edit.html'),
164 164 defaults=defaults,
165 165 encoding="UTF-8",
166 166 force_defaults=False
167 167 )
@@ -1,178 +1,178 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # settings controller for pylons
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on June 30, 2010
22 22 settings controller for pylons
23 23 @author: marcink
24 24 """
25 25 from formencode import htmlfill
26 26 from pylons import tmpl_context as c, request, url
27 27 from pylons.controllers.util import redirect
28 28 from pylons.i18n.translation import _
29 29 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAllDecorator
30 30 from rhodecode.lib.base import BaseController, render
31 31 from rhodecode.lib.utils import invalidate_cache, action_logger
32 32 from rhodecode.model.forms import RepoSettingsForm, RepoForkForm
33 33 from rhodecode.model.repo import RepoModel
34 34 import formencode
35 35 import logging
36 36 import rhodecode.lib.helpers as h
37 37 import traceback
38 38
39 39 log = logging.getLogger(__name__)
40 40
41 41 class SettingsController(BaseController):
42 42
43 43 @LoginRequired()
44 44 @HasRepoPermissionAllDecorator('repository.admin')
45 45 def __before__(self):
46 46 super(SettingsController, self).__before__()
47 47
48 48 def index(self, repo_name):
49 49 repo_model = RepoModel()
50 50 c.repo_info = repo = repo_model.get_by_repo_name(repo_name)
51 51 if not repo:
52 52 h.flash(_('%s repository is not mapped to db perhaps'
53 53 ' it was created or renamed from the filesystem'
54 54 ' please run the application again'
55 55 ' in order to rescan repositories') % repo_name,
56 56 category='error')
57 57
58 58 return redirect(url('home'))
59 defaults = c.repo_info.__dict__
59 defaults = c.repo_info.__dict__.copy()
60 60 defaults.update({'user':c.repo_info.user.username})
61 61 c.users_array = repo_model.get_users_js()
62 62
63 63 for p in c.repo_info.repo_to_perm:
64 64 defaults.update({'perm_%s' % p.user.username:
65 65 p.permission.permission_name})
66 66
67 67 return htmlfill.render(
68 68 render('settings/repo_settings.html'),
69 69 defaults=defaults,
70 70 encoding="UTF-8",
71 71 force_defaults=False
72 72 )
73 73
74 74 def update(self, repo_name):
75 75 repo_model = RepoModel()
76 76 changed_name = repo_name
77 77 _form = RepoSettingsForm(edit=True, old_data={'repo_name':repo_name})()
78 78 try:
79 79 form_result = _form.to_python(dict(request.POST))
80 80 repo_model.update(repo_name, form_result)
81 81 invalidate_cache('get_repo_cached_%s' % repo_name)
82 82 h.flash(_('Repository %s updated successfully' % repo_name),
83 83 category='success')
84 84 changed_name = form_result['repo_name']
85 85 action_logger(self.rhodecode_user, 'user_updated_repo',
86 86 changed_name, '', self.sa)
87 87 except formencode.Invalid, errors:
88 88 c.repo_info = repo_model.get_by_repo_name(repo_name)
89 89 c.users_array = repo_model.get_users_js()
90 90 errors.value.update({'user':c.repo_info.user.username})
91 91 return htmlfill.render(
92 92 render('settings/repo_settings.html'),
93 93 defaults=errors.value,
94 94 errors=errors.error_dict or {},
95 95 prefix_error=False,
96 96 encoding="UTF-8")
97 97 except Exception:
98 98 log.error(traceback.format_exc())
99 99 h.flash(_('error occurred during update of repository %s') \
100 100 % repo_name, category='error')
101 101
102 102 return redirect(url('repo_settings_home', repo_name=changed_name))
103 103
104 104
105 105
106 106 def delete(self, repo_name):
107 107 """DELETE /repos/repo_name: Delete an existing item"""
108 108 # Forms posted to this method should contain a hidden field:
109 109 # <input type="hidden" name="_method" value="DELETE" />
110 110 # Or using helpers:
111 111 # h.form(url('repo_settings_delete', repo_name=ID),
112 112 # method='delete')
113 113 # url('repo_settings_delete', repo_name=ID)
114 114
115 115 repo_model = RepoModel()
116 116 repo = repo_model.get_by_repo_name(repo_name)
117 117 if not repo:
118 118 h.flash(_('%s repository is not mapped to db perhaps'
119 119 ' it was moved or renamed from the filesystem'
120 120 ' please run the application again'
121 121 ' in order to rescan repositories') % repo_name,
122 122 category='error')
123 123
124 124 return redirect(url('home'))
125 125 try:
126 126 action_logger(self.rhodecode_user, 'user_deleted_repo',
127 127 repo_name, '', self.sa)
128 128 repo_model.delete(repo)
129 129 invalidate_cache('get_repo_cached_%s' % repo_name)
130 130 h.flash(_('deleted repository %s') % repo_name, category='success')
131 131 except Exception:
132 132 h.flash(_('An error occurred during deletion of %s') % repo_name,
133 133 category='error')
134 134
135 135 return redirect(url('home'))
136 136
137 137 def fork(self, repo_name):
138 138 repo_model = RepoModel()
139 139 c.repo_info = repo = repo_model.get_by_repo_name(repo_name)
140 140 if not repo:
141 141 h.flash(_('%s repository is not mapped to db perhaps'
142 142 ' it was created or renamed from the filesystem'
143 143 ' please run the application again'
144 144 ' in order to rescan repositories') % repo_name,
145 145 category='error')
146 146
147 147 return redirect(url('home'))
148 148
149 149 return render('settings/repo_fork.html')
150 150
151 151
152 152
153 153 def fork_create(self, repo_name):
154 154 repo_model = RepoModel()
155 155 c.repo_info = repo_model.get_by_repo_name(repo_name)
156 156 _form = RepoForkForm(old_data={'repo_type':c.repo_info.repo_type})()
157 157 form_result = {}
158 158 try:
159 159 form_result = _form.to_python(dict(request.POST))
160 160 form_result.update({'repo_name':repo_name})
161 161 repo_model.create_fork(form_result, c.rhodecode_user)
162 162 h.flash(_('forked %s repository as %s') \
163 163 % (repo_name, form_result['fork_name']),
164 164 category='success')
165 165 action_logger(self.rhodecode_user,
166 166 'user_forked_repo:%s' % form_result['fork_name'],
167 167 repo_name, '', self.sa)
168 168 except formencode.Invalid, errors:
169 169 c.new_repo = errors.value['fork_name']
170 170 r = render('settings/repo_fork.html')
171 171
172 172 return htmlfill.render(
173 173 r,
174 174 defaults=errors.value,
175 175 errors=errors.error_dict or {},
176 176 prefix_error=False,
177 177 encoding="UTF-8")
178 178 return redirect(url('home'))
@@ -1,383 +1,377 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.scm
4 4 ~~~~~~~~~~~~~~~~~~~
5 5
6 6 Scm model for RhodeCode
7 7
8 8 :created_on: Apr 9, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27 import os
28 28 import time
29 29 import traceback
30 30 import logging
31 31
32 32 from vcs import get_backend
33 33 from vcs.utils.helpers import get_scm
34 34 from vcs.exceptions import RepositoryError, VCSError
35 35 from vcs.utils.lazy import LazyProperty
36 36
37 37 from mercurial import ui
38 38
39 39 from beaker.cache import cache_region, region_invalidate
40 40
41 41 from rhodecode import BACKENDS
42 42 from rhodecode.lib import helpers as h
43 43 from rhodecode.lib.auth import HasRepoPermissionAny
44 44 from rhodecode.lib.utils import get_repos, make_ui, action_logger
45 45 from rhodecode.model import BaseModel
46 46 from rhodecode.model.user import UserModel
47 47
48 48 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
49 49 UserFollowing, UserLog
50 50 from rhodecode.model.caching_query import FromCache
51 51
52 52 from sqlalchemy.orm import joinedload
53 53 from sqlalchemy.orm.session import make_transient
54 54 from sqlalchemy.exc import DatabaseError
55 55
56 56 log = logging.getLogger(__name__)
57 57
58 58
59 59 class UserTemp(object):
60 60 def __init__(self, user_id):
61 61 self.user_id = user_id
62 62 class RepoTemp(object):
63 63 def __init__(self, repo_id):
64 64 self.repo_id = repo_id
65 65
66 66 class ScmModel(BaseModel):
67 67 """Generic Scm Model
68 68 """
69 69
70 70 @LazyProperty
71 71 def repos_path(self):
72 72 """Get's the repositories root path from database
73 73 """
74 74
75 75 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
76 76
77 77 return q.ui_value
78 78
79 79 def repo_scan(self, repos_path, baseui):
80 80 """Listing of repositories in given path. This path should not be a
81 81 repository itself. Return a dictionary of repository objects
82 82
83 83 :param repos_path: path to directory containing repositories
84 84 :param baseui
85 85 """
86 86
87 87 log.info('scanning for repositories in %s', repos_path)
88 88
89 89 if not isinstance(baseui, ui.ui):
90 90 baseui = make_ui('db')
91 91 repos_list = {}
92 92
93 93 for name, path in get_repos(repos_path):
94 94 try:
95 95 if repos_list.has_key(name):
96 96 raise RepositoryError('Duplicate repository name %s '
97 97 'found in %s' % (name, path))
98 98 else:
99 99
100 100 klass = get_backend(path[0])
101 101
102 102 if path[0] == 'hg' and path[0] in BACKENDS.keys():
103 103 repos_list[name] = klass(path[1], baseui=baseui)
104 104
105 105 if path[0] == 'git' and path[0] in BACKENDS.keys():
106 106 repos_list[name] = klass(path[1])
107 107 except OSError:
108 108 continue
109 109
110 110 return repos_list
111 111
112 112 def get_repos(self, all_repos=None):
113 113 """Get all repos from db and for each repo create it's backend instance.
114 114 and fill that backed with information from database
115 115
116 116 :param all_repos: give specific repositories list, good for filtering
117 117 """
118 118
119 119 if all_repos is None:
120 120 all_repos = self.sa.query(Repository)\
121 121 .order_by(Repository.repo_name).all()
122 122
123 123 #get the repositories that should be invalidated
124 124 invalidation_list = [str(x.cache_key) for x in \
125 125 self.sa.query(CacheInvalidation.cache_key)\
126 126 .filter(CacheInvalidation.cache_active == False)\
127 127 .all()]
128 128
129 129 for r in all_repos:
130 130
131 131 repo = self.get(r.repo_name, invalidation_list)
132 132
133 133 if repo is not None:
134 134 last_change = repo.last_change
135 135 tip = h.get_changeset_safe(repo, 'tip')
136 136
137 137 tmp_d = {}
138 138 tmp_d['name'] = repo.name
139 139 tmp_d['name_sort'] = tmp_d['name'].lower()
140 140 tmp_d['description'] = repo.dbrepo.description
141 141 tmp_d['description_sort'] = tmp_d['description']
142 142 tmp_d['last_change'] = last_change
143 143 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
144 144 tmp_d['tip'] = tip.raw_id
145 145 tmp_d['tip_sort'] = tip.revision
146 146 tmp_d['rev'] = tip.revision
147
148 #dirty hack for some problems
149 usr = repo.dbrepo.user
150 if isinstance(usr, basestring):
151 usr = UserModel(self.sa).get_by_username(repo.dbrepo.user)
152
153 tmp_d['contact'] = usr.full_contact
147 tmp_d['contact'] = repo.dbrepo.user.full_contact
154 148 tmp_d['contact_sort'] = tmp_d['contact']
155 149 tmp_d['repo_archives'] = list(repo._get_archives())
156 150 tmp_d['last_msg'] = tip.message
157 151 tmp_d['repo'] = repo
158 152 yield tmp_d
159 153
160 154 def get_repo(self, repo_name):
161 155 return self.get(repo_name)
162 156
163 157 def get(self, repo_name, invalidation_list=None):
164 158 """Get's repository from given name, creates BackendInstance and
165 159 propagates it's data from database with all additional information
166 160
167 161 :param repo_name:
168 162 :param invalidation_list: if a invalidation list is given the get
169 163 method should not manually check if this repository needs
170 164 invalidation and just invalidate the repositories in list
171 165
172 166 """
173 167 if not HasRepoPermissionAny('repository.read', 'repository.write',
174 168 'repository.admin')(repo_name, 'get repo check'):
175 169 return
176 170
177 171 #======================================================================
178 172 # CACHE FUNCTION
179 173 #======================================================================
180 174 @cache_region('long_term')
181 175 def _get_repo(repo_name):
182 176
183 177 repo_path = os.path.join(self.repos_path, repo_name)
184 178
185 179 try:
186 180 alias = get_scm(repo_path)[0]
187 181
188 182 log.debug('Creating instance of %s repository', alias)
189 183 backend = get_backend(alias)
190 184 except VCSError:
191 185 log.error(traceback.format_exc())
192 186 return
193 187
194 188 if alias == 'hg':
195 189 from pylons import app_globals as g
196 190 repo = backend(repo_path, create=False, baseui=g.baseui)
197 191 #skip hidden web repository
198 192 if repo._get_hidden():
199 193 return
200 194 else:
201 195 repo = backend(repo_path, create=False)
202 196
203 197 dbrepo = self.sa.query(Repository)\
204 198 .options(joinedload(Repository.fork))\
205 199 .options(joinedload(Repository.user))\
206 200 .filter(Repository.repo_name == repo_name)\
207 201 .scalar()
208 202
209 203 make_transient(dbrepo)
210 204 if dbrepo.user:
211 205 make_transient(dbrepo.user)
212 206 if dbrepo.fork:
213 207 make_transient(dbrepo.fork)
214 208
215 209 repo.dbrepo = dbrepo
216 210 return repo
217 211
218 212 pre_invalidate = True
219 213 if invalidation_list is not None:
220 214 pre_invalidate = repo_name in invalidation_list
221 215
222 216 if pre_invalidate:
223 217 invalidate = self._should_invalidate(repo_name)
224 218
225 219 if invalidate:
226 220 log.info('invalidating cache for repository %s', repo_name)
227 221 region_invalidate(_get_repo, None, repo_name)
228 222 self._mark_invalidated(invalidate)
229 223
230 224 return _get_repo(repo_name)
231 225
232 226
233 227
234 228 def mark_for_invalidation(self, repo_name):
235 229 """Puts cache invalidation task into db for
236 230 further global cache invalidation
237 231
238 232 :param repo_name: this repo that should invalidation take place
239 233 """
240 234
241 235 log.debug('marking %s for invalidation', repo_name)
242 236 cache = self.sa.query(CacheInvalidation)\
243 237 .filter(CacheInvalidation.cache_key == repo_name).scalar()
244 238
245 239 if cache:
246 240 #mark this cache as inactive
247 241 cache.cache_active = False
248 242 else:
249 243 log.debug('cache key not found in invalidation db -> creating one')
250 244 cache = CacheInvalidation(repo_name)
251 245
252 246 try:
253 247 self.sa.add(cache)
254 248 self.sa.commit()
255 249 except (DatabaseError,):
256 250 log.error(traceback.format_exc())
257 251 self.sa.rollback()
258 252
259 253
260 254 def toggle_following_repo(self, follow_repo_id, user_id):
261 255
262 256 f = self.sa.query(UserFollowing)\
263 257 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
264 258 .filter(UserFollowing.user_id == user_id).scalar()
265 259
266 260 if f is not None:
267 261
268 262 try:
269 263 self.sa.delete(f)
270 264 self.sa.commit()
271 265 action_logger(UserTemp(user_id),
272 266 'stopped_following_repo',
273 267 RepoTemp(follow_repo_id))
274 268 return
275 269 except:
276 270 log.error(traceback.format_exc())
277 271 self.sa.rollback()
278 272 raise
279 273
280 274
281 275 try:
282 276 f = UserFollowing()
283 277 f.user_id = user_id
284 278 f.follows_repo_id = follow_repo_id
285 279 self.sa.add(f)
286 280 self.sa.commit()
287 281 action_logger(UserTemp(user_id),
288 282 'started_following_repo',
289 283 RepoTemp(follow_repo_id))
290 284 except:
291 285 log.error(traceback.format_exc())
292 286 self.sa.rollback()
293 287 raise
294 288
295 289 def toggle_following_user(self, follow_user_id , user_id):
296 290 f = self.sa.query(UserFollowing)\
297 291 .filter(UserFollowing.follows_user_id == follow_user_id)\
298 292 .filter(UserFollowing.user_id == user_id).scalar()
299 293
300 294 if f is not None:
301 295 try:
302 296 self.sa.delete(f)
303 297 self.sa.commit()
304 298 return
305 299 except:
306 300 log.error(traceback.format_exc())
307 301 self.sa.rollback()
308 302 raise
309 303
310 304 try:
311 305 f = UserFollowing()
312 306 f.user_id = user_id
313 307 f.follows_user_id = follow_user_id
314 308 self.sa.add(f)
315 309 self.sa.commit()
316 310 except:
317 311 log.error(traceback.format_exc())
318 312 self.sa.rollback()
319 313 raise
320 314
321 315 def is_following_repo(self, repo_name, user_id):
322 316 r = self.sa.query(Repository)\
323 317 .filter(Repository.repo_name == repo_name).scalar()
324 318
325 319 f = self.sa.query(UserFollowing)\
326 320 .filter(UserFollowing.follows_repository == r)\
327 321 .filter(UserFollowing.user_id == user_id).scalar()
328 322
329 323 return f is not None
330 324
331 325 def is_following_user(self, username, user_id):
332 326 u = UserModel(self.sa).get_by_username(username)
333 327
334 328 f = self.sa.query(UserFollowing)\
335 329 .filter(UserFollowing.follows_user == u)\
336 330 .filter(UserFollowing.user_id == user_id).scalar()
337 331
338 332 return f is not None
339 333
340 334 def get_followers(self, repo_id):
341 335 return self.sa.query(UserFollowing)\
342 336 .filter(UserFollowing.follows_repo_id == repo_id).count()
343 337
344 338 def get_forks(self, repo_id):
345 339 return self.sa.query(Repository)\
346 340 .filter(Repository.fork_id == repo_id).count()
347 341
348 342
349 343 def get_unread_journal(self):
350 344 return self.sa.query(UserLog).count()
351 345
352 346
353 347 def _should_invalidate(self, repo_name):
354 348 """Looks up database for invalidation signals for this repo_name
355 349
356 350 :param repo_name:
357 351 """
358 352
359 353 ret = self.sa.query(CacheInvalidation)\
360 354 .options(FromCache('sql_cache_short',
361 355 'get_invalidation_%s' % repo_name))\
362 356 .filter(CacheInvalidation.cache_key == repo_name)\
363 357 .filter(CacheInvalidation.cache_active == False)\
364 358 .scalar()
365 359
366 360 return ret
367 361
368 362 def _mark_invalidated(self, cache_key):
369 363 """ Marks all occurences of cache to invaldation as already invalidated
370 364
371 365 :param cache_key:
372 366 """
373 367
374 368 if cache_key:
375 369 log.debug('marking %s as already invalidated', cache_key)
376 370 try:
377 371 cache_key.cache_active = True
378 372 self.sa.add(cache_key)
379 373 self.sa.commit()
380 374 except (DatabaseError,):
381 375 log.error(traceback.format_exc())
382 376 self.sa.rollback()
383 377
General Comments 0
You need to be logged in to leave comments. Login now