##// END OF EJS Templates
fixes for vcs 0.2.0and new slicing methods
marcink -
r1082:c2440bad beta
parent child Browse files
Show More
@@ -1,342 +1,342 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-2011 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, repo_name_slug
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 occurred 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 = 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
151 151 if c.repo_info.stats:
152 152 last_rev = c.repo_info.stats.stat_on_revision
153 153 else:
154 154 last_rev = 0
155 155 c.stats_revision = last_rev
156 156 repo, dbrepo = ScmModel().get(repo_name, retval='repo')
157 c.repo_last_rev = repo.revisions[-1] if repo.revisions else 0
157 c.repo_last_rev = repo.count() if repo.revisions else 0
158 158
159 159 if last_rev == 0:
160 160 c.stats_percentage = 0
161 161 else:
162 162 c.stats_percentage = '%.2f' % ((float((last_rev)) /
163 163 c.repo_last_rev) * 100)
164 164
165 165 c.users_array = repo_model.get_users_js()
166 166 c.users_groups_array = repo_model.get_users_groups_js()
167 167
168 168 errors.value.update({'user':c.repo_info.user.username})
169 169 return htmlfill.render(
170 170 render('admin/repos/repo_edit.html'),
171 171 defaults=errors.value,
172 172 errors=errors.error_dict or {},
173 173 prefix_error=False,
174 174 encoding="UTF-8")
175 175
176 176 except Exception:
177 177 log.error(traceback.format_exc())
178 178 h.flash(_('error occurred during update of repository %s') \
179 179 % repo_name, category='error')
180 180
181 181 return redirect(url('edit_repo', repo_name=changed_name))
182 182
183 183 @HasPermissionAllDecorator('hg.admin')
184 184 def delete(self, repo_name):
185 185 """DELETE /repos/repo_name: Delete an existing item"""
186 186 # Forms posted to this method should contain a hidden field:
187 187 # <input type="hidden" name="_method" value="DELETE" />
188 188 # Or using helpers:
189 189 # h.form(url('repo', repo_name=ID),
190 190 # method='delete')
191 191 # url('repo', repo_name=ID)
192 192
193 193 repo_model = RepoModel()
194 194 repo = repo_model.get_by_repo_name(repo_name)
195 195 if not repo:
196 196 h.flash(_('%s repository is not mapped to db perhaps'
197 197 ' it was moved or renamed from the filesystem'
198 198 ' please run the application again'
199 199 ' in order to rescan repositories') % repo_name,
200 200 category='error')
201 201
202 202 return redirect(url('repos'))
203 203 try:
204 204 action_logger(self.rhodecode_user, 'admin_deleted_repo',
205 205 repo_name, '', self.sa)
206 206 repo_model.delete(repo)
207 207 invalidate_cache('get_repo_cached_%s' % repo_name)
208 208 h.flash(_('deleted repository %s') % repo_name, category='success')
209 209
210 210 except Exception, e:
211 211 log.error(traceback.format_exc())
212 212 h.flash(_('An error occurred during deletion of %s') % repo_name,
213 213 category='error')
214 214
215 215 return redirect(url('repos'))
216 216
217 217 @HasPermissionAllDecorator('hg.admin')
218 218 def delete_perm_user(self, repo_name):
219 219 """DELETE an existing repository permission user
220 220
221 221 :param repo_name:
222 222 """
223 223
224 224 try:
225 225 repo_model = RepoModel()
226 226 repo_model.delete_perm_user(request.POST, repo_name)
227 227 except Exception, e:
228 228 h.flash(_('An error occurred during deletion of repository user'),
229 229 category='error')
230 230 raise HTTPInternalServerError()
231 231
232 232 @HasPermissionAllDecorator('hg.admin')
233 233 def delete_perm_users_group(self, repo_name):
234 234 """DELETE an existing repository permission users group
235 235
236 236 :param repo_name:
237 237 """
238 238 try:
239 239 repo_model = RepoModel()
240 240 repo_model.delete_perm_users_group(request.POST, repo_name)
241 241 except Exception, e:
242 242 h.flash(_('An error occurred during deletion of repository'
243 243 ' users groups'),
244 244 category='error')
245 245 raise HTTPInternalServerError()
246 246
247 247 @HasPermissionAllDecorator('hg.admin')
248 248 def repo_stats(self, repo_name):
249 249 """DELETE an existing repository statistics
250 250
251 251 :param repo_name:
252 252 """
253 253
254 254 try:
255 255 repo_model = RepoModel()
256 256 repo_model.delete_stats(repo_name)
257 257 except Exception, e:
258 258 h.flash(_('An error occurred during deletion of repository stats'),
259 259 category='error')
260 260 return redirect(url('edit_repo', repo_name=repo_name))
261 261
262 262 @HasPermissionAllDecorator('hg.admin')
263 263 def repo_cache(self, repo_name):
264 264 """INVALIDATE existing repository cache
265 265
266 266 :param repo_name:
267 267 """
268 268
269 269 try:
270 270 ScmModel().mark_for_invalidation(repo_name)
271 271 except Exception, e:
272 272 h.flash(_('An error occurred during cache invalidation'),
273 273 category='error')
274 274 return redirect(url('edit_repo', repo_name=repo_name))
275 275
276 276 @HasPermissionAllDecorator('hg.admin')
277 277 def show(self, repo_name, format='html'):
278 278 """GET /repos/repo_name: Show a specific item"""
279 279 # url('repo', repo_name=ID)
280 280
281 281 @HasPermissionAllDecorator('hg.admin')
282 282 def edit(self, repo_name, format='html'):
283 283 """GET /repos/repo_name/edit: Form to edit an existing item"""
284 284 # url('edit_repo', repo_name=ID)
285 285 repo, dbrepo = ScmModel().get(repo_name, retval='repo')
286 286
287 287 repo_model = RepoModel()
288 288 c.repo_info = repo_model.get_by_repo_name(repo_name)
289 289
290 290 if c.repo_info is None:
291 291 h.flash(_('%s repository is not mapped to db perhaps'
292 292 ' it was created or renamed from the filesystem'
293 293 ' please run the application again'
294 294 ' in order to rescan repositories') % repo_name,
295 295 category='error')
296 296
297 297 return redirect(url('repos'))
298 298
299 299 if c.repo_info.stats:
300 300 last_rev = c.repo_info.stats.stat_on_revision
301 301 else:
302 302 last_rev = 0
303 303 c.stats_revision = last_rev
304 304
305 c.repo_last_rev = repo.revisions[-1] if repo.revisions else 0
305 c.repo_last_rev = repo.count() if repo.revisions else 0
306 306
307 307 if last_rev == 0 or c.repo_last_rev == 0:
308 308 c.stats_percentage = 0
309 309 else:
310 310 c.stats_percentage = '%.2f' % ((float((last_rev)) /
311 311 c.repo_last_rev) * 100)
312 312
313 313 c.users_array = repo_model.get_users_js()
314 314 c.users_groups_array = repo_model.get_users_groups_js()
315 315
316 316 defaults = c.repo_info.get_dict()
317 317
318 318 #fill owner
319 319 if c.repo_info.user:
320 320 defaults.update({'user':c.repo_info.user.username})
321 321 else:
322 322 replacement_user = self.sa.query(User)\
323 323 .filter(User.admin == True).first().username
324 324 defaults.update({'user':replacement_user})
325 325
326 326
327 327 #fill repository users
328 328 for p in c.repo_info.repo_to_perm:
329 329 defaults.update({'u_perm_%s' % p.user.username:
330 330 p.permission.permission_name})
331 331
332 332 #fill repository groups
333 333 for p in c.repo_info.users_group_to_perm:
334 334 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
335 335 p.permission.permission_name})
336 336
337 337 return htmlfill.render(
338 338 render('admin/repos/repo_edit.html'),
339 339 defaults=defaults,
340 340 encoding="UTF-8",
341 341 force_defaults=False
342 342 )
@@ -1,213 +1,212 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.changeset
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 changeset controller for pylons showoing changes beetween
7 7 revisions
8 8
9 9 :created_on: Apr 25, 2010
10 10 :author: marcink
11 11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software; you can redistribute it and/or
15 15 # modify it under the terms of the GNU General Public License
16 16 # as published by the Free Software Foundation; version 2
17 17 # of the License or (at your opinion) any later version of the license.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program; if not, write to the Free Software
26 26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 27 # MA 02110-1301, USA.
28 28 import logging
29 29 import traceback
30 30
31 31 from pylons import tmpl_context as c, url, request, response
32 32 from pylons.i18n.translation import _
33 33 from pylons.controllers.util import redirect
34 34
35 35 import rhodecode.lib.helpers as h
36 36 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
37 37 from rhodecode.lib.base import BaseRepoController, render
38 38 from rhodecode.lib.utils import EmptyChangeset
39 39
40 40 from vcs.exceptions import RepositoryError, ChangesetError, \
41 41 ChangesetDoesNotExistError
42 42 from vcs.nodes import FileNode
43 43 from vcs.utils import diffs as differ
44 44 from vcs.utils.ordered_dict import OrderedDict
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48 class ChangesetController(BaseRepoController):
49 49
50 50 @LoginRequired()
51 51 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 52 'repository.admin')
53 53 def __before__(self):
54 54 super(ChangesetController, self).__before__()
55 55
56 56 def index(self, revision):
57 57
58 58 def wrap_to_table(str):
59 59
60 60 return '''<table class="code-difftable">
61 61 <tr class="line">
62 62 <td class="lineno new"></td>
63 63 <td class="code"><pre>%s</pre></td>
64 64 </tr>
65 65 </table>''' % str
66 66
67 67 #get ranges of revisions if preset
68 68 rev_range = revision.split('...')[:2]
69 69 range_limit = 50
70 70 try:
71 71 if len(rev_range) == 2:
72 72 rev_start = rev_range[0]
73 73 rev_end = rev_range[1]
74 rev_ranges = c.rhodecode_repo.get_changesets_ranges(rev_start, rev_end,
75 range_limit)
74 rev_ranges = list(c.rhodecode_repo[rev_start:rev_end])
76 75 else:
77 76 rev_ranges = [c.rhodecode_repo.get_changeset(revision)]
78 77
79 78 c.cs_ranges = list(rev_ranges)
80 79
81 80 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
82 81 log.error(traceback.format_exc())
83 82 h.flash(str(e), category='warning')
84 83 return redirect(url('home'))
85 84
86 85 c.changes = OrderedDict()
87 86 c.sum_added = 0
88 87 c.sum_removed = 0
89 88
90 89
91 90 for changeset in c.cs_ranges:
92 91 c.changes[changeset.raw_id] = []
93 92 try:
94 93 changeset_parent = changeset.parents[0]
95 94 except IndexError:
96 95 changeset_parent = None
97 96
98 97
99 98 #==================================================================
100 99 # ADDED FILES
101 100 #==================================================================
102 101 for node in changeset.added:
103 102 filenode_old = FileNode(node.path, '', EmptyChangeset())
104 103 if filenode_old.is_binary or node.is_binary:
105 104 diff = wrap_to_table(_('binary file'))
106 105 else:
107 106 c.sum_added += node.size
108 107 if c.sum_added < self.cut_off_limit:
109 108 f_udiff = differ.get_udiff(filenode_old, node)
110 109 diff = differ.DiffProcessor(f_udiff).as_html()
111 110
112 111 else:
113 112 diff = wrap_to_table(_('Changeset is to big and was cut'
114 113 ' off, see raw changeset instead'))
115 114
116 115 cs1 = None
117 116 cs2 = node.last_changeset.raw_id
118 117 c.changes[changeset.raw_id].append(('added', node, diff, cs1, cs2))
119 118
120 119 #==================================================================
121 120 # CHANGED FILES
122 121 #==================================================================
123 122 for node in changeset.changed:
124 123 try:
125 124 filenode_old = changeset_parent.get_node(node.path)
126 125 except ChangesetError:
127 126 filenode_old = FileNode(node.path, '', EmptyChangeset())
128 127
129 128 if filenode_old.is_binary or node.is_binary:
130 129 diff = wrap_to_table(_('binary file'))
131 130 else:
132 131
133 132 if c.sum_removed < self.cut_off_limit:
134 133 f_udiff = differ.get_udiff(filenode_old, node)
135 134 diff = differ.DiffProcessor(f_udiff).as_html()
136 135 if diff:
137 136 c.sum_removed += len(diff)
138 137 else:
139 138 diff = wrap_to_table(_('Changeset is to big and was cut'
140 139 ' off, see raw changeset instead'))
141 140
142 141
143 142 cs1 = filenode_old.last_changeset.raw_id
144 143 cs2 = node.last_changeset.raw_id
145 144 c.changes[changeset.raw_id].append(('changed', node, diff, cs1, cs2))
146 145
147 146 #==================================================================
148 147 # REMOVED FILES
149 148 #==================================================================
150 149 for node in changeset.removed:
151 150 c.changes[changeset.raw_id].append(('removed', node, None, None, None))
152 151
153 152 if len(c.cs_ranges) == 1:
154 153 c.changeset = c.cs_ranges[0]
155 154 c.changes = c.changes[c.changeset.raw_id]
156 155
157 156 return render('changeset/changeset.html')
158 157 else:
159 158 return render('changeset/changeset_range.html')
160 159
161 160 def raw_changeset(self, revision):
162 161
163 162 method = request.GET.get('diff', 'show')
164 163 try:
165 164 c.scm_type = c.rhodecode_repo.alias
166 165 c.changeset = c.rhodecode_repo.get_changeset(revision)
167 166 except RepositoryError:
168 167 log.error(traceback.format_exc())
169 168 return redirect(url('home'))
170 169 else:
171 170 try:
172 171 c.changeset_parent = c.changeset.parents[0]
173 172 except IndexError:
174 173 c.changeset_parent = None
175 174 c.changes = []
176 175
177 176 for node in c.changeset.added:
178 177 filenode_old = FileNode(node.path, '')
179 178 if filenode_old.is_binary or node.is_binary:
180 179 diff = _('binary file') + '\n'
181 180 else:
182 181 f_udiff = differ.get_gitdiff(filenode_old, node)
183 182 diff = differ.DiffProcessor(f_udiff).raw_diff()
184 183
185 184 cs1 = None
186 185 cs2 = node.last_changeset.raw_id
187 186 c.changes.append(('added', node, diff, cs1, cs2))
188 187
189 188 for node in c.changeset.changed:
190 189 filenode_old = c.changeset_parent.get_node(node.path)
191 190 if filenode_old.is_binary or node.is_binary:
192 191 diff = _('binary file')
193 192 else:
194 193 f_udiff = differ.get_gitdiff(filenode_old, node)
195 194 diff = differ.DiffProcessor(f_udiff).raw_diff()
196 195
197 196 cs1 = filenode_old.last_changeset.raw_id
198 197 cs2 = node.last_changeset.raw_id
199 198 c.changes.append(('changed', node, diff, cs1, cs2))
200 199
201 200 response.content_type = 'text/plain'
202 201
203 202 if method == 'download':
204 203 response.content_disposition = 'attachment; filename=%s.patch' % revision
205 204
206 205 parent = True if len(c.changeset.parents) > 0 else False
207 206 c.parent_tmpl = 'Parent %s' % c.changeset.parents[0].raw_id if parent else ''
208 207
209 208 c.diffs = ''
210 209 for x in c.changes:
211 210 c.diffs += x[2]
212 211
213 212 return render('changeset/raw_changeset.html')
@@ -1,170 +1,170 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.summary
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Summary controller for Rhodecode
7 7
8 8 :created_on: Apr 18, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 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 calendar
29 29 import logging
30 30 from time import mktime
31 31 from datetime import datetime, timedelta, date
32 32
33 33 from vcs.exceptions import ChangesetError
34 34
35 35 from pylons import tmpl_context as c, request, url
36 36 from pylons.i18n.translation import _
37 37
38 38 from rhodecode.model.db import Statistics
39 39
40 40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
41 41 from rhodecode.lib.base import BaseRepoController, render
42 42 from rhodecode.lib.utils import OrderedDict, EmptyChangeset
43 43
44 44 from rhodecode.lib.celerylib import run_task
45 45 from rhodecode.lib.celerylib.tasks import get_commits_stats
46 46
47 47 from webhelpers.paginate import Page
48 48
49 49 try:
50 50 import json
51 51 except ImportError:
52 52 #python 2.5 compatibility
53 53 import simplejson as json
54 54 log = logging.getLogger(__name__)
55 55
56 56 class SummaryController(BaseRepoController):
57 57
58 58 @LoginRequired()
59 59 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
60 60 'repository.admin')
61 61 def __before__(self):
62 62 super(SummaryController, self).__before__()
63 63
64 64 def index(self):
65 65 c.repo, dbrepo = self.scm_model.get(c.repo_name)
66 66 c.dbrepo = dbrepo
67 67
68 68 c.following = self.scm_model.is_following_repo(c.repo_name,
69 69 c.rhodecode_user.user_id)
70 70 def url_generator(**kw):
71 71 return url('shortlog_home', repo_name=c.repo_name, **kw)
72 72
73 73 c.repo_changesets = Page(c.repo, page=1, items_per_page=10,
74 74 url=url_generator)
75 75
76 76 e = request.environ
77 77
78 78 if self.rhodecode_user.username == 'default':
79 79 #for default(anonymous) user we don't need to pass credentials
80 80 username = ''
81 81 password = ''
82 82 else:
83 83 username = str(c.rhodecode_user.username)
84 84 password = '@'
85 85
86 86 uri = u'%(protocol)s://%(user)s%(password)s%(host)s%(prefix)s/%(repo_name)s' % {
87 87 'protocol': e.get('wsgi.url_scheme'),
88 88 'user':username,
89 89 'password':password,
90 90 'host':e.get('HTTP_HOST'),
91 91 'prefix':e.get('SCRIPT_NAME'),
92 92 'repo_name':c.repo_name, }
93 93 c.clone_repo_url = uri
94 94 c.repo_tags = OrderedDict()
95 95 for name, hash in c.repo.tags.items()[:10]:
96 96 try:
97 97 c.repo_tags[name] = c.repo.get_changeset(hash)
98 98 except ChangesetError:
99 99 c.repo_tags[name] = EmptyChangeset(hash)
100 100
101 101 c.repo_branches = OrderedDict()
102 102 for name, hash in c.repo.branches.items()[:10]:
103 103 try:
104 104 c.repo_branches[name] = c.repo.get_changeset(hash)
105 105 except ChangesetError:
106 106 c.repo_branches[name] = EmptyChangeset(hash)
107 107
108 108 td = date.today() + timedelta(days=1)
109 109 td_1m = td - timedelta(days=calendar.mdays[td.month])
110 110 td_1y = td - timedelta(days=365)
111 111
112 112 ts_min_m = mktime(td_1m.timetuple())
113 113 ts_min_y = mktime(td_1y.timetuple())
114 114 ts_max_y = mktime(td.timetuple())
115 115
116 116 if dbrepo.enable_statistics:
117 117 c.no_data_msg = _('No data loaded yet')
118 118 run_task(get_commits_stats, c.repo.name, ts_min_y, ts_max_y)
119 119 else:
120 c.no_data_msg = _('Statistics update are disabled for this repository')
120 c.no_data_msg = _('Statistics are disabled for this repository')
121 121 c.ts_min = ts_min_m
122 122 c.ts_max = ts_max_y
123 123
124 124 stats = self.sa.query(Statistics)\
125 125 .filter(Statistics.repository == dbrepo)\
126 126 .scalar()
127 127
128 128
129 129 if stats and stats.languages:
130 130 c.no_data = False is dbrepo.enable_statistics
131 131 lang_stats = json.loads(stats.languages)
132 132 c.commit_data = stats.commit_activity
133 133 c.overview_data = stats.commit_activity_combined
134 134 c.trending_languages = json.dumps(OrderedDict(
135 135 sorted(lang_stats.items(), reverse=True,
136 136 key=lambda k: k[1])[:10]
137 137 )
138 138 )
139 139 else:
140 140 c.commit_data = json.dumps({})
141 141 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10] ])
142 142 c.trending_languages = json.dumps({})
143 143 c.no_data = True
144 144
145 145 c.enable_downloads = dbrepo.enable_downloads
146 146 if c.enable_downloads:
147 147 c.download_options = self._get_download_links(c.repo)
148 148
149 149 return render('summary/summary.html')
150 150
151 151
152 152
153 153 def _get_download_links(self, repo):
154 154
155 155 download_l = []
156 156
157 157 branches_group = ([], _("Branches"))
158 158 tags_group = ([], _("Tags"))
159 159
160 160 for name, chs in c.rhodecode_repo.branches.items():
161 161 #chs = chs.split(':')[-1]
162 162 branches_group[0].append((chs, name),)
163 163 download_l.append(branches_group)
164 164
165 165 for name, chs in c.rhodecode_repo.tags.items():
166 166 #chs = chs.split(':')[-1]
167 167 tags_group[0].append((chs, name),)
168 168 download_l.append(tags_group)
169 169
170 170 return download_l
@@ -1,105 +1,107 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.celerylib.__init__
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 celery libs for RhodeCode
7 7
8 8 :created_on: Nov 27, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 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 os
29 29 import sys
30 30 import socket
31 31 import traceback
32 32 import logging
33 33
34 34 from hashlib import md5
35 35 from decorator import decorator
36 from pylons import config
37
36 38 from vcs.utils.lazy import LazyProperty
37 39
38 40 from rhodecode.lib import str2bool
39 41 from rhodecode.lib.pidlock import DaemonLock, LockHeld
40 42
41 43 from celery.messaging import establish_connection
42 from pylons import config
44
43 45
44 46 log = logging.getLogger(__name__)
45 47
46 48 try:
47 49 CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
48 50 except KeyError:
49 51 CELERY_ON = False
50 52
51 53 class ResultWrapper(object):
52 54 def __init__(self, task):
53 55 self.task = task
54 56
55 57 @LazyProperty
56 58 def result(self):
57 59 return self.task
58 60
59 61 def run_task(task, *args, **kwargs):
60 62 if CELERY_ON:
61 63 try:
62 64 t = task.apply_async(args=args, kwargs=kwargs)
63 65 log.info('running task %s:%s', t.task_id, task)
64 66 return t
65 67 except socket.error, e:
66 68 if e.errno == 111:
67 69 log.debug('Unable to connect to celeryd. Sync execution')
68 70 else:
69 71 log.error(traceback.format_exc())
70 72 except KeyError, e:
71 73 log.debug('Unable to connect to celeryd. Sync execution')
72 74 except Exception, e:
73 75 log.error(traceback.format_exc())
74 76
75 77 log.debug('executing task %s in sync mode', task)
76 78 return ResultWrapper(task(*args, **kwargs))
77 79
78 80
79 81 def locked_task(func):
80 82 def __wrapper(func, *fargs, **fkwargs):
81 83 params = list(fargs)
82 84 params.extend(['%s-%s' % ar for ar in fkwargs.items()])
83 85
84 86 lockkey = 'task_%s' % \
85 87 md5(str(func.__name__) + '-' + \
86 88 '-'.join(map(str, params))).hexdigest()
87 89 log.info('running task with lockkey %s', lockkey)
88 90 try:
89 91 l = DaemonLock(lockkey)
90 92 ret = func(*fargs, **fkwargs)
91 93 l.release()
92 94 return ret
93 95 except LockHeld:
94 96 log.info('LockHeld')
95 97 return 'Task with key %s already running' % lockkey
96 98
97 99 return decorator(__wrapper, func)
98 100
99 101
100 102
101 103
102 104
103 105
104 106
105 107
General Comments 0
You need to be logged in to leave comments. Login now