##// END OF EJS Templates
celery: fixed bug where celery was not running
dan -
r265:ed0d2e76 default
parent child Browse files
Show More
@@ -1,878 +1,878 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2013-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 """
23 23 Repositories controller for RhodeCode
24 24 """
25 25
26 26 import logging
27 27 import traceback
28 28
29 29 import formencode
30 30 from formencode import htmlfill
31 31 from pylons import request, tmpl_context as c, url
32 32 from pylons.controllers.util import redirect
33 33 from pylons.i18n.translation import _
34 34 from webob.exc import HTTPForbidden, HTTPNotFound, HTTPBadRequest
35 35
36 36 from rhodecode.lib import auth, helpers as h
37 37 from rhodecode.lib.auth import (
38 38 LoginRequired, HasPermissionAllDecorator,
39 39 HasRepoPermissionAllDecorator, NotAnonymous, HasPermissionAny,
40 40 HasRepoGroupPermissionAny, HasRepoPermissionAnyDecorator)
41 41 from rhodecode.lib.base import BaseRepoController, render
42 42 from rhodecode.lib.ext_json import json
43 43 from rhodecode.lib.exceptions import AttachedForksError
44 44 from rhodecode.lib.utils import action_logger, repo_name_slug, jsonify
45 45 from rhodecode.lib.utils2 import safe_int
46 46 from rhodecode.lib.vcs import RepositoryError
47 47 from rhodecode.model.db import (
48 48 User, Repository, UserFollowing, RepoGroup, RepositoryField)
49 49 from rhodecode.model.forms import (
50 50 RepoForm, RepoFieldForm, RepoPermsForm, RepoVcsSettingsForm,
51 51 IssueTrackerPatternsForm)
52 52 from rhodecode.model.meta import Session
53 53 from rhodecode.model.repo import RepoModel
54 54 from rhodecode.model.scm import ScmModel, RepoGroupList, RepoList
55 55 from rhodecode.model.settings import (
56 56 SettingsModel, IssueTrackerSettingsModel, VcsSettingsModel,
57 57 SettingNotFound)
58 58
59 59 log = logging.getLogger(__name__)
60 60
61 61
62 62 class ReposController(BaseRepoController):
63 63 """
64 64 REST Controller styled on the Atom Publishing Protocol"""
65 65 # To properly map this controller, ensure your config/routing.py
66 66 # file has a resource setup:
67 67 # map.resource('repo', 'repos')
68 68
69 69 @LoginRequired()
70 70 def __before__(self):
71 71 super(ReposController, self).__before__()
72 72
73 73 def _load_repo(self, repo_name):
74 74 repo_obj = Repository.get_by_repo_name(repo_name)
75 75
76 76 if repo_obj is None:
77 77 h.not_mapped_error(repo_name)
78 78 return redirect(url('repos'))
79 79
80 80 return repo_obj
81 81
82 82 def __load_defaults(self, repo=None):
83 83 acl_groups = RepoGroupList(RepoGroup.query().all(),
84 84 perm_set=['group.write', 'group.admin'])
85 85 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
86 86 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
87 87
88 88 # in case someone no longer have a group.write access to a repository
89 89 # pre fill the list with this entry, we don't care if this is the same
90 90 # but it will allow saving repo data properly.
91 91
92 92 repo_group = None
93 93 if repo:
94 94 repo_group = repo.group
95 95 if repo_group and unicode(repo_group.group_id) not in c.repo_groups_choices:
96 96 c.repo_groups_choices.append(unicode(repo_group.group_id))
97 97 c.repo_groups.append(RepoGroup._generate_choice(repo_group))
98 98
99 99 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
100 100 c.landing_revs_choices = choices
101 101
102 102 def __load_data(self, repo_name=None):
103 103 """
104 104 Load defaults settings for edit, and update
105 105
106 106 :param repo_name:
107 107 """
108 108 c.repo_info = self._load_repo(repo_name)
109 109 self.__load_defaults(c.repo_info)
110 110
111 111 # override defaults for exact repo info here git/hg etc
112 112 if not c.repository_requirements_missing:
113 113 choices, c.landing_revs = ScmModel().get_repo_landing_revs(
114 114 c.repo_info)
115 115 c.landing_revs_choices = choices
116 116 defaults = RepoModel()._get_defaults(repo_name)
117 117
118 118 return defaults
119 119
120 120 def _log_creation_exception(self, e, repo_name):
121 121 reason = None
122 122 if len(e.args) == 2:
123 123 reason = e.args[1]
124 124
125 125 if reason == 'INVALID_CERTIFICATE':
126 126 log.exception(
127 127 'Exception creating a repository: invalid certificate')
128 128 msg = (_('Error creating repository %s: invalid certificate')
129 129 % repo_name)
130 130 else:
131 131 log.exception("Exception creating a repository")
132 132 msg = (_('Error creating repository %s')
133 133 % repo_name)
134 134
135 135 return msg
136 136
137 137 @NotAnonymous()
138 138 def index(self, format='html'):
139 139 """GET /repos: All items in the collection"""
140 140 # url('repos')
141 141
142 142 repo_list = Repository.get_all_repos()
143 143 c.repo_list = RepoList(repo_list, perm_set=['repository.admin'])
144 144 repos_data = RepoModel().get_repos_as_dict(
145 145 repo_list=c.repo_list, admin=True, super_user_actions=True)
146 146 # json used to render the grid
147 147 c.data = json.dumps(repos_data)
148 148
149 149 return render('admin/repos/repos.html')
150 150
151 151 # perms check inside
152 152 @NotAnonymous()
153 153 @auth.CSRFRequired()
154 154 def create(self):
155 155 """
156 156 POST /repos: Create a new item"""
157 157 # url('repos')
158 158
159 159 self.__load_defaults()
160 160 form_result = {}
161 161 task_id = None
162 162 try:
163 163 # CanWriteToGroup validators checks permissions of this POST
164 164 form_result = RepoForm(repo_groups=c.repo_groups_choices,
165 165 landing_revs=c.landing_revs_choices)()\
166 166 .to_python(dict(request.POST))
167 167
168 168 # create is done sometimes async on celery, db transaction
169 169 # management is handled there.
170 170 task = RepoModel().create(form_result, c.rhodecode_user.user_id)
171 171 from celery.result import BaseAsyncResult
172 172 if isinstance(task, BaseAsyncResult):
173 173 task_id = task.task_id
174 174 except formencode.Invalid as errors:
175 175 c.personal_repo_group = RepoGroup.get_by_group_name(
176 176 c.rhodecode_user.username)
177 177 return htmlfill.render(
178 178 render('admin/repos/repo_add.html'),
179 179 defaults=errors.value,
180 180 errors=errors.error_dict or {},
181 181 prefix_error=False,
182 182 encoding="UTF-8",
183 183 force_defaults=False)
184 184
185 185 except Exception as e:
186 186 msg = self._log_creation_exception(e, form_result.get('repo_name'))
187 187 h.flash(msg, category='error')
188 188 return redirect(url('home'))
189 189
190 190 return redirect(h.url('repo_creating_home',
191 191 repo_name=form_result['repo_name_full'],
192 192 task_id=task_id))
193 193
194 194 # perms check inside
195 195 @NotAnonymous()
196 196 def create_repository(self):
197 197 """GET /_admin/create_repository: Form to create a new item"""
198 198 new_repo = request.GET.get('repo', '')
199 199 parent_group = request.GET.get('parent_group')
200 200 if not HasPermissionAny('hg.admin', 'hg.create.repository')():
201 201 # you're not super admin nor have global create permissions,
202 202 # but maybe you have at least write permission to a parent group ?
203 203 _gr = RepoGroup.get(parent_group)
204 204 gr_name = _gr.group_name if _gr else None
205 205 # create repositories with write permission on group is set to true
206 206 create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
207 207 group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
208 208 group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
209 209 if not (group_admin or (group_write and create_on_write)):
210 210 raise HTTPForbidden
211 211
212 212 acl_groups = RepoGroupList(RepoGroup.query().all(),
213 213 perm_set=['group.write', 'group.admin'])
214 214 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
215 215 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
216 216 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
217 217 c.personal_repo_group = RepoGroup.get_by_group_name(c.rhodecode_user.username)
218 218 c.new_repo = repo_name_slug(new_repo)
219 219
220 220 ## apply the defaults from defaults page
221 221 defaults = SettingsModel().get_default_repo_settings(strip_prefix=True)
222 222 # set checkbox to autochecked
223 223 defaults['repo_copy_permissions'] = True
224 224 if parent_group:
225 225 defaults.update({'repo_group': parent_group})
226 226
227 227 return htmlfill.render(
228 228 render('admin/repos/repo_add.html'),
229 229 defaults=defaults,
230 230 errors={},
231 231 prefix_error=False,
232 232 encoding="UTF-8",
233 233 force_defaults=False
234 234 )
235 235
236 236 @NotAnonymous()
237 237 def repo_creating(self, repo_name):
238 238 c.repo = repo_name
239 239 c.task_id = request.GET.get('task_id')
240 240 if not c.repo:
241 241 raise HTTPNotFound()
242 242 return render('admin/repos/repo_creating.html')
243 243
244 244 @NotAnonymous()
245 245 @jsonify
246 246 def repo_check(self, repo_name):
247 247 c.repo = repo_name
248 248 task_id = request.GET.get('task_id')
249 249
250 250 if task_id and task_id not in ['None']:
251 from rhodecode import CELERY_ENABLED
251 import rhodecode
252 252 from celery.result import AsyncResult
253 if CELERY_ENABLED:
253 if rhodecode.CELERY_ENABLED:
254 254 task = AsyncResult(task_id)
255 255 if task.failed():
256 256 msg = self._log_creation_exception(task.result, c.repo)
257 257 h.flash(msg, category='error')
258 258 return redirect(url('home'), code=501)
259 259
260 260 repo = Repository.get_by_repo_name(repo_name)
261 261 if repo and repo.repo_state == Repository.STATE_CREATED:
262 262 if repo.clone_uri:
263 263 clone_uri = repo.clone_uri_hidden
264 264 h.flash(_('Created repository %s from %s')
265 265 % (repo.repo_name, clone_uri), category='success')
266 266 else:
267 267 repo_url = h.link_to(repo.repo_name,
268 268 h.url('summary_home',
269 269 repo_name=repo.repo_name))
270 270 fork = repo.fork
271 271 if fork:
272 272 fork_name = fork.repo_name
273 273 h.flash(h.literal(_('Forked repository %s as %s')
274 274 % (fork_name, repo_url)), category='success')
275 275 else:
276 276 h.flash(h.literal(_('Created repository %s') % repo_url),
277 277 category='success')
278 278 return {'result': True}
279 279 return {'result': False}
280 280
281 281 @HasRepoPermissionAllDecorator('repository.admin')
282 282 @auth.CSRFRequired()
283 283 def update(self, repo_name):
284 284 """
285 285 PUT /repos/repo_name: Update an existing item"""
286 286 # Forms posted to this method should contain a hidden field:
287 287 # <input type="hidden" name="_method" value="PUT" />
288 288 # Or using helpers:
289 289 # h.form(url('repo', repo_name=ID),
290 290 # method='put')
291 291 # url('repo', repo_name=ID)
292 292
293 293 self.__load_data(repo_name)
294 294 c.active = 'settings'
295 295 c.repo_fields = RepositoryField.query()\
296 296 .filter(RepositoryField.repository == c.repo_info).all()
297 297
298 298 repo_model = RepoModel()
299 299 changed_name = repo_name
300 300
301 301 # override the choices with extracted revisions !
302 302 c.personal_repo_group = RepoGroup.get_by_group_name(
303 303 c.rhodecode_user.username)
304 304 repo = Repository.get_by_repo_name(repo_name)
305 305 old_data = {
306 306 'repo_name': repo_name,
307 307 'repo_group': repo.group.get_dict() if repo.group else {},
308 308 'repo_type': repo.repo_type,
309 309 }
310 310 _form = RepoForm(
311 311 edit=True, old_data=old_data, repo_groups=c.repo_groups_choices,
312 312 landing_revs=c.landing_revs_choices, allow_disabled=True)()
313 313
314 314 try:
315 315 form_result = _form.to_python(dict(request.POST))
316 316 repo = repo_model.update(repo_name, **form_result)
317 317 ScmModel().mark_for_invalidation(repo_name)
318 318 h.flash(_('Repository %s updated successfully') % repo_name,
319 319 category='success')
320 320 changed_name = repo.repo_name
321 321 action_logger(c.rhodecode_user, 'admin_updated_repo',
322 322 changed_name, self.ip_addr, self.sa)
323 323 Session().commit()
324 324 except formencode.Invalid as errors:
325 325 defaults = self.__load_data(repo_name)
326 326 defaults.update(errors.value)
327 327 return htmlfill.render(
328 328 render('admin/repos/repo_edit.html'),
329 329 defaults=defaults,
330 330 errors=errors.error_dict or {},
331 331 prefix_error=False,
332 332 encoding="UTF-8",
333 333 force_defaults=False)
334 334
335 335 except Exception:
336 336 log.exception("Exception during update of repository")
337 337 h.flash(_('Error occurred during update of repository %s') \
338 338 % repo_name, category='error')
339 339 return redirect(url('edit_repo', repo_name=changed_name))
340 340
341 341 @HasRepoPermissionAllDecorator('repository.admin')
342 342 @auth.CSRFRequired()
343 343 def delete(self, repo_name):
344 344 """
345 345 DELETE /repos/repo_name: Delete an existing item"""
346 346 # Forms posted to this method should contain a hidden field:
347 347 # <input type="hidden" name="_method" value="DELETE" />
348 348 # Or using helpers:
349 349 # h.form(url('repo', repo_name=ID),
350 350 # method='delete')
351 351 # url('repo', repo_name=ID)
352 352
353 353 repo_model = RepoModel()
354 354 repo = repo_model.get_by_repo_name(repo_name)
355 355 if not repo:
356 356 h.not_mapped_error(repo_name)
357 357 return redirect(url('repos'))
358 358 try:
359 359 _forks = repo.forks.count()
360 360 handle_forks = None
361 361 if _forks and request.POST.get('forks'):
362 362 do = request.POST['forks']
363 363 if do == 'detach_forks':
364 364 handle_forks = 'detach'
365 365 h.flash(_('Detached %s forks') % _forks, category='success')
366 366 elif do == 'delete_forks':
367 367 handle_forks = 'delete'
368 368 h.flash(_('Deleted %s forks') % _forks, category='success')
369 369 repo_model.delete(repo, forks=handle_forks)
370 370 action_logger(c.rhodecode_user, 'admin_deleted_repo',
371 371 repo_name, self.ip_addr, self.sa)
372 372 ScmModel().mark_for_invalidation(repo_name)
373 373 h.flash(_('Deleted repository %s') % repo_name, category='success')
374 374 Session().commit()
375 375 except AttachedForksError:
376 376 h.flash(_('Cannot delete %s it still contains attached forks')
377 377 % repo_name, category='warning')
378 378
379 379 except Exception:
380 380 log.exception("Exception during deletion of repository")
381 381 h.flash(_('An error occurred during deletion of %s') % repo_name,
382 382 category='error')
383 383
384 384 return redirect(url('repos'))
385 385
386 386 @HasPermissionAllDecorator('hg.admin')
387 387 def show(self, repo_name, format='html'):
388 388 """GET /repos/repo_name: Show a specific item"""
389 389 # url('repo', repo_name=ID)
390 390
391 391 @HasRepoPermissionAllDecorator('repository.admin')
392 392 def edit(self, repo_name):
393 393 """GET /repo_name/settings: Form to edit an existing item"""
394 394 # url('edit_repo', repo_name=ID)
395 395 defaults = self.__load_data(repo_name)
396 396 if 'clone_uri' in defaults:
397 397 del defaults['clone_uri']
398 398
399 399 c.repo_fields = RepositoryField.query()\
400 400 .filter(RepositoryField.repository == c.repo_info).all()
401 401 c.personal_repo_group = RepoGroup.get_by_group_name(
402 402 c.rhodecode_user.username)
403 403 c.active = 'settings'
404 404 return htmlfill.render(
405 405 render('admin/repos/repo_edit.html'),
406 406 defaults=defaults,
407 407 encoding="UTF-8",
408 408 force_defaults=False)
409 409
410 410 @HasRepoPermissionAllDecorator('repository.admin')
411 411 def edit_permissions(self, repo_name):
412 412 """GET /repo_name/settings: Form to edit an existing item"""
413 413 # url('edit_repo', repo_name=ID)
414 414 c.repo_info = self._load_repo(repo_name)
415 415 c.active = 'permissions'
416 416 defaults = RepoModel()._get_defaults(repo_name)
417 417
418 418 return htmlfill.render(
419 419 render('admin/repos/repo_edit.html'),
420 420 defaults=defaults,
421 421 encoding="UTF-8",
422 422 force_defaults=False)
423 423
424 424 @HasRepoPermissionAllDecorator('repository.admin')
425 425 @auth.CSRFRequired()
426 426 def edit_permissions_update(self, repo_name):
427 427 form = RepoPermsForm()().to_python(request.POST)
428 428 RepoModel().update_permissions(repo_name,
429 429 form['perm_additions'], form['perm_updates'], form['perm_deletions'])
430 430
431 431 #TODO: implement this
432 432 #action_logger(c.rhodecode_user, 'admin_changed_repo_permissions',
433 433 # repo_name, self.ip_addr, self.sa)
434 434 Session().commit()
435 435 h.flash(_('Repository permissions updated'), category='success')
436 436 return redirect(url('edit_repo_perms', repo_name=repo_name))
437 437
438 438 @HasRepoPermissionAllDecorator('repository.admin')
439 439 def edit_fields(self, repo_name):
440 440 """GET /repo_name/settings: Form to edit an existing item"""
441 441 # url('edit_repo', repo_name=ID)
442 442 c.repo_info = self._load_repo(repo_name)
443 443 c.repo_fields = RepositoryField.query()\
444 444 .filter(RepositoryField.repository == c.repo_info).all()
445 445 c.active = 'fields'
446 446 if request.POST:
447 447
448 448 return redirect(url('repo_edit_fields'))
449 449 return render('admin/repos/repo_edit.html')
450 450
451 451 @HasRepoPermissionAllDecorator('repository.admin')
452 452 @auth.CSRFRequired()
453 453 def create_repo_field(self, repo_name):
454 454 try:
455 455 form_result = RepoFieldForm()().to_python(dict(request.POST))
456 456 RepoModel().add_repo_field(
457 457 repo_name, form_result['new_field_key'],
458 458 field_type=form_result['new_field_type'],
459 459 field_value=form_result['new_field_value'],
460 460 field_label=form_result['new_field_label'],
461 461 field_desc=form_result['new_field_desc'])
462 462
463 463 Session().commit()
464 464 except Exception as e:
465 465 log.exception("Exception creating field")
466 466 msg = _('An error occurred during creation of field')
467 467 if isinstance(e, formencode.Invalid):
468 468 msg += ". " + e.msg
469 469 h.flash(msg, category='error')
470 470 return redirect(url('edit_repo_fields', repo_name=repo_name))
471 471
472 472 @HasRepoPermissionAllDecorator('repository.admin')
473 473 @auth.CSRFRequired()
474 474 def delete_repo_field(self, repo_name, field_id):
475 475 field = RepositoryField.get_or_404(field_id)
476 476 try:
477 477 RepoModel().delete_repo_field(repo_name, field.field_key)
478 478 Session().commit()
479 479 except Exception as e:
480 480 log.exception("Exception during removal of field")
481 481 msg = _('An error occurred during removal of field')
482 482 h.flash(msg, category='error')
483 483 return redirect(url('edit_repo_fields', repo_name=repo_name))
484 484
485 485 @HasRepoPermissionAllDecorator('repository.admin')
486 486 def edit_advanced(self, repo_name):
487 487 """GET /repo_name/settings: Form to edit an existing item"""
488 488 # url('edit_repo', repo_name=ID)
489 489 c.repo_info = self._load_repo(repo_name)
490 490 c.default_user_id = User.get_default_user().user_id
491 491 c.in_public_journal = UserFollowing.query()\
492 492 .filter(UserFollowing.user_id == c.default_user_id)\
493 493 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
494 494
495 495 c.active = 'advanced'
496 496 c.has_origin_repo_read_perm = False
497 497 if c.repo_info.fork:
498 498 c.has_origin_repo_read_perm = h.HasRepoPermissionAny(
499 499 'repository.write', 'repository.read', 'repository.admin')(
500 500 c.repo_info.fork.repo_name, 'repo set as fork page')
501 501
502 502 if request.POST:
503 503 return redirect(url('repo_edit_advanced'))
504 504 return render('admin/repos/repo_edit.html')
505 505
506 506 @HasRepoPermissionAllDecorator('repository.admin')
507 507 @auth.CSRFRequired()
508 508 def edit_advanced_journal(self, repo_name):
509 509 """
510 510 Set's this repository to be visible in public journal,
511 511 in other words assing default user to follow this repo
512 512
513 513 :param repo_name:
514 514 """
515 515
516 516 try:
517 517 repo_id = Repository.get_by_repo_name(repo_name).repo_id
518 518 user_id = User.get_default_user().user_id
519 519 self.scm_model.toggle_following_repo(repo_id, user_id)
520 520 h.flash(_('Updated repository visibility in public journal'),
521 521 category='success')
522 522 Session().commit()
523 523 except Exception:
524 524 h.flash(_('An error occurred during setting this'
525 525 ' repository in public journal'),
526 526 category='error')
527 527
528 528 return redirect(url('edit_repo_advanced', repo_name=repo_name))
529 529
530 530 @HasRepoPermissionAllDecorator('repository.admin')
531 531 @auth.CSRFRequired()
532 532 def edit_advanced_fork(self, repo_name):
533 533 """
534 534 Mark given repository as a fork of another
535 535
536 536 :param repo_name:
537 537 """
538 538
539 539 new_fork_id = request.POST.get('id_fork_of')
540 540 try:
541 541
542 542 if new_fork_id and not new_fork_id.isdigit():
543 543 log.error('Given fork id %s is not an INT', new_fork_id)
544 544
545 545 fork_id = safe_int(new_fork_id)
546 546 repo = ScmModel().mark_as_fork(repo_name, fork_id,
547 547 c.rhodecode_user.username)
548 548 fork = repo.fork.repo_name if repo.fork else _('Nothing')
549 549 Session().commit()
550 550 h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork),
551 551 category='success')
552 552 except RepositoryError as e:
553 553 log.exception("Repository Error occurred")
554 554 h.flash(str(e), category='error')
555 555 except Exception as e:
556 556 log.exception("Exception while editing fork")
557 557 h.flash(_('An error occurred during this operation'),
558 558 category='error')
559 559
560 560 return redirect(url('edit_repo_advanced', repo_name=repo_name))
561 561
562 562 @HasRepoPermissionAllDecorator('repository.admin')
563 563 @auth.CSRFRequired()
564 564 def edit_advanced_locking(self, repo_name):
565 565 """
566 566 Unlock repository when it is locked !
567 567
568 568 :param repo_name:
569 569 """
570 570 try:
571 571 repo = Repository.get_by_repo_name(repo_name)
572 572 if request.POST.get('set_lock'):
573 573 Repository.lock(repo, c.rhodecode_user.user_id,
574 574 lock_reason=Repository.LOCK_WEB)
575 575 h.flash(_('Locked repository'), category='success')
576 576 elif request.POST.get('set_unlock'):
577 577 Repository.unlock(repo)
578 578 h.flash(_('Unlocked repository'), category='success')
579 579 except Exception as e:
580 580 log.exception("Exception during unlocking")
581 581 h.flash(_('An error occurred during unlocking'),
582 582 category='error')
583 583 return redirect(url('edit_repo_advanced', repo_name=repo_name))
584 584
585 585 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
586 586 @auth.CSRFRequired()
587 587 def toggle_locking(self, repo_name):
588 588 """
589 589 Toggle locking of repository by simple GET call to url
590 590
591 591 :param repo_name:
592 592 """
593 593
594 594 try:
595 595 repo = Repository.get_by_repo_name(repo_name)
596 596
597 597 if repo.enable_locking:
598 598 if repo.locked[0]:
599 599 Repository.unlock(repo)
600 600 action = _('Unlocked')
601 601 else:
602 602 Repository.lock(repo, c.rhodecode_user.user_id,
603 603 lock_reason=Repository.LOCK_WEB)
604 604 action = _('Locked')
605 605
606 606 h.flash(_('Repository has been %s') % action,
607 607 category='success')
608 608 except Exception:
609 609 log.exception("Exception during unlocking")
610 610 h.flash(_('An error occurred during unlocking'),
611 611 category='error')
612 612 return redirect(url('summary_home', repo_name=repo_name))
613 613
614 614 @HasRepoPermissionAllDecorator('repository.admin')
615 615 @auth.CSRFRequired()
616 616 def edit_caches(self, repo_name):
617 617 """PUT /{repo_name}/settings/caches: invalidate the repo caches."""
618 618 try:
619 619 ScmModel().mark_for_invalidation(repo_name, delete=True)
620 620 Session().commit()
621 621 h.flash(_('Cache invalidation successful'),
622 622 category='success')
623 623 except Exception:
624 624 log.exception("Exception during cache invalidation")
625 625 h.flash(_('An error occurred during cache invalidation'),
626 626 category='error')
627 627
628 628 return redirect(url('edit_repo_caches', repo_name=c.repo_name))
629 629
630 630 @HasRepoPermissionAllDecorator('repository.admin')
631 631 def edit_caches_form(self, repo_name):
632 632 """GET /repo_name/settings: Form to edit an existing item"""
633 633 # url('edit_repo', repo_name=ID)
634 634 c.repo_info = self._load_repo(repo_name)
635 635 c.active = 'caches'
636 636
637 637 return render('admin/repos/repo_edit.html')
638 638
639 639 @HasRepoPermissionAllDecorator('repository.admin')
640 640 @auth.CSRFRequired()
641 641 def edit_remote(self, repo_name):
642 642 """PUT /{repo_name}/settings/remote: edit the repo remote."""
643 643 try:
644 644 ScmModel().pull_changes(repo_name, c.rhodecode_user.username)
645 645 h.flash(_('Pulled from remote location'), category='success')
646 646 except Exception:
647 647 log.exception("Exception during pull from remote")
648 648 h.flash(_('An error occurred during pull from remote location'),
649 649 category='error')
650 650 return redirect(url('edit_repo_remote', repo_name=c.repo_name))
651 651
652 652 @HasRepoPermissionAllDecorator('repository.admin')
653 653 def edit_remote_form(self, repo_name):
654 654 """GET /repo_name/settings: Form to edit an existing item"""
655 655 # url('edit_repo', repo_name=ID)
656 656 c.repo_info = self._load_repo(repo_name)
657 657 c.active = 'remote'
658 658
659 659 return render('admin/repos/repo_edit.html')
660 660
661 661 @HasRepoPermissionAllDecorator('repository.admin')
662 662 @auth.CSRFRequired()
663 663 def edit_statistics(self, repo_name):
664 664 """PUT /{repo_name}/settings/statistics: reset the repo statistics."""
665 665 try:
666 666 RepoModel().delete_stats(repo_name)
667 667 Session().commit()
668 668 except Exception as e:
669 669 log.error(traceback.format_exc())
670 670 h.flash(_('An error occurred during deletion of repository stats'),
671 671 category='error')
672 672 return redirect(url('edit_repo_statistics', repo_name=c.repo_name))
673 673
674 674 @HasRepoPermissionAllDecorator('repository.admin')
675 675 def edit_statistics_form(self, repo_name):
676 676 """GET /repo_name/settings: Form to edit an existing item"""
677 677 # url('edit_repo', repo_name=ID)
678 678 c.repo_info = self._load_repo(repo_name)
679 679 repo = c.repo_info.scm_instance()
680 680
681 681 if c.repo_info.stats:
682 682 # this is on what revision we ended up so we add +1 for count
683 683 last_rev = c.repo_info.stats.stat_on_revision + 1
684 684 else:
685 685 last_rev = 0
686 686 c.stats_revision = last_rev
687 687
688 688 c.repo_last_rev = repo.count()
689 689
690 690 if last_rev == 0 or c.repo_last_rev == 0:
691 691 c.stats_percentage = 0
692 692 else:
693 693 c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100)
694 694
695 695 c.active = 'statistics'
696 696
697 697 return render('admin/repos/repo_edit.html')
698 698
699 699 @HasRepoPermissionAllDecorator('repository.admin')
700 700 @auth.CSRFRequired()
701 701 def repo_issuetracker_test(self, repo_name):
702 702 if request.is_xhr:
703 703 return h.urlify_commit_message(
704 704 request.POST.get('test_text', ''),
705 705 repo_name)
706 706 else:
707 707 raise HTTPBadRequest()
708 708
709 709 @HasRepoPermissionAllDecorator('repository.admin')
710 710 @auth.CSRFRequired()
711 711 def repo_issuetracker_delete(self, repo_name):
712 712 uid = request.POST.get('uid')
713 713 repo_settings = IssueTrackerSettingsModel(repo=repo_name)
714 714 try:
715 715 repo_settings.delete_entries(uid)
716 716 except Exception:
717 717 h.flash(_('Error occurred during deleting issue tracker entry'),
718 718 category='error')
719 719 else:
720 720 h.flash(_('Removed issue tracker entry'), category='success')
721 721 return redirect(url('repo_settings_issuetracker',
722 722 repo_name=repo_name))
723 723
724 724 def _update_patterns(self, form, repo_settings):
725 725 for uid in form['delete_patterns']:
726 726 repo_settings.delete_entries(uid)
727 727
728 728 for pattern in form['patterns']:
729 729 for setting, value, type_ in pattern:
730 730 sett = repo_settings.create_or_update_setting(
731 731 setting, value, type_)
732 732 Session().add(sett)
733 733
734 734 Session().commit()
735 735
736 736 @HasRepoPermissionAllDecorator('repository.admin')
737 737 @auth.CSRFRequired()
738 738 def repo_issuetracker_save(self, repo_name):
739 739 # Save inheritance
740 740 repo_settings = IssueTrackerSettingsModel(repo=repo_name)
741 741 inherited = (request.POST.get('inherit_global_issuetracker')
742 742 == "inherited")
743 743 repo_settings.inherit_global_settings = inherited
744 744 Session().commit()
745 745
746 746 form = IssueTrackerPatternsForm()().to_python(request.POST)
747 747 if form:
748 748 self._update_patterns(form, repo_settings)
749 749
750 750 h.flash(_('Updated issue tracker entries'), category='success')
751 751 return redirect(url('repo_settings_issuetracker',
752 752 repo_name=repo_name))
753 753
754 754 @HasRepoPermissionAllDecorator('repository.admin')
755 755 def repo_issuetracker(self, repo_name):
756 756 """GET /admin/settings/issue-tracker: All items in the collection"""
757 757 c.active = 'issuetracker'
758 758 c.data = 'data'
759 759 c.repo_info = self._load_repo(repo_name)
760 760
761 761 repo = Repository.get_by_repo_name(repo_name)
762 762 c.settings_model = IssueTrackerSettingsModel(repo=repo)
763 763 c.global_patterns = c.settings_model.get_global_settings()
764 764 c.repo_patterns = c.settings_model.get_repo_settings()
765 765
766 766 return render('admin/repos/repo_edit.html')
767 767
768 768 @HasRepoPermissionAllDecorator('repository.admin')
769 769 def repo_settings_vcs(self, repo_name):
770 770 """GET /{repo_name}/settings/vcs/: All items in the collection"""
771 771
772 772 model = VcsSettingsModel(repo=repo_name)
773 773
774 774 c.active = 'vcs'
775 775 c.global_svn_branch_patterns = model.get_global_svn_branch_patterns()
776 776 c.global_svn_tag_patterns = model.get_global_svn_tag_patterns()
777 777 c.svn_branch_patterns = model.get_repo_svn_branch_patterns()
778 778 c.svn_tag_patterns = model.get_repo_svn_tag_patterns()
779 779 c.repo_info = self._load_repo(repo_name)
780 780 defaults = self._vcs_form_defaults(repo_name)
781 781 c.inherit_global_settings = defaults['inherit_global_settings']
782 782
783 783 return htmlfill.render(
784 784 render('admin/repos/repo_edit.html'),
785 785 defaults=defaults,
786 786 encoding="UTF-8",
787 787 force_defaults=False)
788 788
789 789 @HasRepoPermissionAllDecorator('repository.admin')
790 790 @auth.CSRFRequired()
791 791 def repo_settings_vcs_update(self, repo_name):
792 792 """POST /{repo_name}/settings/vcs/: All items in the collection"""
793 793 c.active = 'vcs'
794 794
795 795 model = VcsSettingsModel(repo=repo_name)
796 796 c.global_svn_branch_patterns = model.get_global_svn_branch_patterns()
797 797 c.global_svn_tag_patterns = model.get_global_svn_tag_patterns()
798 798 c.svn_branch_patterns = model.get_repo_svn_branch_patterns()
799 799 c.svn_tag_patterns = model.get_repo_svn_tag_patterns()
800 800 c.repo_info = self._load_repo(repo_name)
801 801 defaults = self._vcs_form_defaults(repo_name)
802 802 c.inherit_global_settings = defaults['inherit_global_settings']
803 803
804 804 application_form = RepoVcsSettingsForm(repo_name)()
805 805 try:
806 806 form_result = application_form.to_python(dict(request.POST))
807 807 except formencode.Invalid as errors:
808 808 h.flash(
809 809 _("Some form inputs contain invalid data."),
810 810 category='error')
811 811 return htmlfill.render(
812 812 render('admin/repos/repo_edit.html'),
813 813 defaults=errors.value,
814 814 errors=errors.error_dict or {},
815 815 prefix_error=False,
816 816 encoding="UTF-8",
817 817 force_defaults=False
818 818 )
819 819
820 820 try:
821 821 inherit_global_settings = form_result['inherit_global_settings']
822 822 model.create_or_update_repo_settings(
823 823 form_result, inherit_global_settings=inherit_global_settings)
824 824 except Exception:
825 825 log.exception("Exception while updating settings")
826 826 h.flash(
827 827 _('Error occurred during updating repository VCS settings'),
828 828 category='error')
829 829 else:
830 830 Session().commit()
831 831 h.flash(_('Updated VCS settings'), category='success')
832 832 return redirect(url('repo_vcs_settings', repo_name=repo_name))
833 833
834 834 return htmlfill.render(
835 835 render('admin/repos/repo_edit.html'),
836 836 defaults=self._vcs_form_defaults(repo_name),
837 837 encoding="UTF-8",
838 838 force_defaults=False)
839 839
840 840 @HasRepoPermissionAllDecorator('repository.admin')
841 841 @auth.CSRFRequired()
842 842 @jsonify
843 843 def repo_delete_svn_pattern(self, repo_name):
844 844 if not request.is_xhr:
845 845 return False
846 846
847 847 delete_pattern_id = request.POST.get('delete_svn_pattern')
848 848 model = VcsSettingsModel(repo=repo_name)
849 849 try:
850 850 model.delete_repo_svn_pattern(delete_pattern_id)
851 851 except SettingNotFound:
852 852 raise HTTPBadRequest()
853 853
854 854 Session().commit()
855 855 return True
856 856
857 857 def _vcs_form_defaults(self, repo_name):
858 858 model = VcsSettingsModel(repo=repo_name)
859 859 global_defaults = model.get_global_settings()
860 860
861 861 repo_defaults = {}
862 862 repo_defaults.update(global_defaults)
863 863 repo_defaults.update(model.get_repo_settings())
864 864
865 865 global_defaults = {
866 866 '{}_inherited'.format(k): global_defaults[k]
867 867 for k in global_defaults}
868 868
869 869 defaults = {
870 870 'inherit_global_settings': model.inherit_global_settings
871 871 }
872 872 defaults.update(global_defaults)
873 873 defaults.update(repo_defaults)
874 874 defaults.update({
875 875 'new_svn_branch': '',
876 876 'new_svn_tag': '',
877 877 })
878 878 return defaults
@@ -1,143 +1,141 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20 """
21 21 celery libs for RhodeCode
22 22 """
23 23
24 24
25 25 import socket
26 26 import logging
27 27
28 28 import rhodecode
29 29
30 30 from os.path import join as jn
31 31 from pylons import config
32 32
33 33 from decorator import decorator
34 34
35 35 from zope.cachedescriptors.property import Lazy as LazyProperty
36 36
37 from rhodecode import CELERY_ENABLED, CELERY_EAGER
38 37 from rhodecode.config import utils
39 38 from rhodecode.lib.utils2 import safe_str, md5_safe, aslist
40 39 from rhodecode.lib.pidlock import DaemonLock, LockHeld
41 40 from rhodecode.lib.vcs import connect_vcs
42 41 from rhodecode.model import meta
43 42
44 43 log = logging.getLogger(__name__)
45 44
46 45
47 46 class ResultWrapper(object):
48 47 def __init__(self, task):
49 48 self.task = task
50 49
51 50 @LazyProperty
52 51 def result(self):
53 52 return self.task
54 53
55 54
56 55 def run_task(task, *args, **kwargs):
57 global CELERY_ENABLED
58 if CELERY_ENABLED:
56 if rhodecode.CELERY_ENABLED:
59 57 try:
60 58 t = task.apply_async(args=args, kwargs=kwargs)
61 59 log.info('running task %s:%s', t.task_id, task)
62 60 return t
63 61
64 62 except socket.error as e:
65 63 if isinstance(e, IOError) and e.errno == 111:
66 log.debug('Unable to connect to celeryd. Sync execution')
67 CELERY_ENABLED = False
64 log.error('Unable to connect to celeryd. Sync execution')
65 rhodecode.CELERY_ENABLED = False
68 66 else:
69 log.exception("Exception while connecting to celeryd.")
67 log.error("Exception while connecting to celeryd.")
70 68 except KeyError as e:
71 log.debug('Unable to connect to celeryd. Sync execution')
69 log.error('Unable to connect to celeryd. Sync execution')
72 70 except Exception as e:
73 71 log.exception(
74 72 "Exception while trying to run task asynchronous. "
75 73 "Fallback to sync execution.")
76
74 else:
77 75 log.debug('executing task %s in sync mode', task)
78 76 return ResultWrapper(task(*args, **kwargs))
79 77
80 78
81 79 def __get_lockkey(func, *fargs, **fkwargs):
82 80 params = list(fargs)
83 81 params.extend(['%s-%s' % ar for ar in fkwargs.items()])
84 82
85 83 func_name = str(func.__name__) if hasattr(func, '__name__') else str(func)
86 84 _lock_key = func_name + '-' + '-'.join(map(safe_str, params))
87 85 return 'task_%s.lock' % (md5_safe(_lock_key),)
88 86
89 87
90 88 def locked_task(func):
91 89 def __wrapper(func, *fargs, **fkwargs):
92 90 lockkey = __get_lockkey(func, *fargs, **fkwargs)
93 91 lockkey_path = config['app_conf']['cache_dir']
94 92
95 93 log.info('running task with lockkey %s' % lockkey)
96 94 try:
97 95 l = DaemonLock(file_=jn(lockkey_path, lockkey))
98 96 ret = func(*fargs, **fkwargs)
99 97 l.release()
100 98 return ret
101 99 except LockHeld:
102 100 log.info('LockHeld')
103 101 return 'Task with key %s already running' % lockkey
104 102
105 103 return decorator(__wrapper, func)
106 104
107 105
108 106 def get_session():
109 if CELERY_ENABLED:
107 if rhodecode.CELERY_ENABLED:
110 108 utils.initialize_database(config)
111 109 sa = meta.Session()
112 110 return sa
113 111
114 112
115 113 def dbsession(func):
116 114 def __wrapper(func, *fargs, **fkwargs):
117 115 try:
118 116 ret = func(*fargs, **fkwargs)
119 117 return ret
120 118 finally:
121 if CELERY_ENABLED and not CELERY_EAGER:
119 if rhodecode.CELERY_ENABLED and not rhodecode.CELERY_EAGER:
122 120 meta.Session.remove()
123 121
124 122 return decorator(__wrapper, func)
125 123
126 124
127 125 def vcsconnection(func):
128 126 def __wrapper(func, *fargs, **fkwargs):
129 if CELERY_ENABLED and not CELERY_EAGER:
127 if rhodecode.CELERY_ENABLED and not rhodecode.CELERY_EAGER:
130 128 backends = config['vcs.backends'] = aslist(
131 129 config.get('vcs.backends', 'hg,git'), sep=',')
132 130 for alias in rhodecode.BACKENDS.keys():
133 131 if alias not in backends:
134 132 del rhodecode.BACKENDS[alias]
135 133 utils.configure_pyro4(config)
136 134 utils.configure_vcs(config)
137 135 connect_vcs(
138 136 config['vcs.server'],
139 137 utils.get_vcs_server_protocol(config))
140 138 ret = func(*fargs, **fkwargs)
141 139 return ret
142 140
143 141 return decorator(__wrapper, func)
@@ -1,284 +1,284 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2012-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 RhodeCode task modules, containing all task that suppose to be run
23 23 by celery daemon
24 24 """
25 25
26 26
27 27 import os
28 28 import logging
29 29
30 30 from celery.task import task
31 31 from pylons import config
32 32
33 from rhodecode import CELERY_ENABLED
33 import rhodecode
34 34 from rhodecode.lib.celerylib import (
35 35 run_task, dbsession, __get_lockkey, LockHeld, DaemonLock,
36 36 get_session, vcsconnection)
37 37 from rhodecode.lib.hooks_base import log_create_repository
38 38 from rhodecode.lib.rcmail.smtp_mailer import SmtpMailer
39 39 from rhodecode.lib.utils import add_cache, action_logger
40 40 from rhodecode.lib.utils2 import safe_int, str2bool
41 41 from rhodecode.model.db import Repository, User
42 42
43 43
44 44 add_cache(config) # pragma: no cover
45 45
46 46
47 47 def get_logger(cls):
48 if CELERY_ENABLED:
48 if rhodecode.CELERY_ENABLED:
49 49 try:
50 50 log = cls.get_logger()
51 51 except Exception:
52 52 log = logging.getLogger(__name__)
53 53 else:
54 54 log = logging.getLogger(__name__)
55 55
56 56 return log
57 57
58 58
59 59 @task(ignore_result=True)
60 60 @dbsession
61 61 def send_email(recipients, subject, body='', html_body='', email_config=None):
62 62 """
63 63 Sends an email with defined parameters from the .ini files.
64 64
65 65 :param recipients: list of recipients, it this is empty the defined email
66 66 address from field 'email_to' is used instead
67 67 :param subject: subject of the mail
68 68 :param body: body of the mail
69 69 :param html_body: html version of body
70 70 """
71 71 log = get_logger(send_email)
72 72
73 73 email_config = email_config or config
74 74 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
75 75 if not recipients:
76 76 # if recipients are not defined we send to email_config + all admins
77 77 admins = [
78 78 u.email for u in User.query().filter(User.admin == True).all()]
79 79 recipients = [email_config.get('email_to')] + admins
80 80
81 81 mail_server = email_config.get('smtp_server') or None
82 82 if mail_server is None:
83 83 log.error("SMTP server information missing. Sending email failed. "
84 84 "Make sure that `smtp_server` variable is configured "
85 85 "inside the .ini file")
86 86 return False
87 87
88 88 mail_from = email_config.get('app_email_from', 'RhodeCode')
89 89 user = email_config.get('smtp_username')
90 90 passwd = email_config.get('smtp_password')
91 91 mail_port = email_config.get('smtp_port')
92 92 tls = str2bool(email_config.get('smtp_use_tls'))
93 93 ssl = str2bool(email_config.get('smtp_use_ssl'))
94 94 debug = str2bool(email_config.get('debug'))
95 95 smtp_auth = email_config.get('smtp_auth')
96 96
97 97 try:
98 98 m = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth,
99 99 mail_port, ssl, tls, debug=debug)
100 100 m.send(recipients, subject, body, html_body)
101 101 except Exception:
102 102 log.exception('Mail sending failed')
103 103 return False
104 104 return True
105 105
106 106
107 107 @task(ignore_result=False)
108 108 @dbsession
109 109 @vcsconnection
110 110 def create_repo(form_data, cur_user):
111 111 from rhodecode.model.repo import RepoModel
112 112 from rhodecode.model.user import UserModel
113 113 from rhodecode.model.settings import SettingsModel
114 114
115 115 log = get_logger(create_repo)
116 116 DBS = get_session()
117 117
118 118 cur_user = UserModel(DBS)._get_user(cur_user)
119 119 owner = cur_user
120 120
121 121 repo_name = form_data['repo_name']
122 122 repo_name_full = form_data['repo_name_full']
123 123 repo_type = form_data['repo_type']
124 124 description = form_data['repo_description']
125 125 private = form_data['repo_private']
126 126 clone_uri = form_data.get('clone_uri')
127 127 repo_group = safe_int(form_data['repo_group'])
128 128 landing_rev = form_data['repo_landing_rev']
129 129 copy_fork_permissions = form_data.get('copy_permissions')
130 130 copy_group_permissions = form_data.get('repo_copy_permissions')
131 131 fork_of = form_data.get('fork_parent_id')
132 132 state = form_data.get('repo_state', Repository.STATE_PENDING)
133 133
134 134 # repo creation defaults, private and repo_type are filled in form
135 135 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
136 136 enable_statistics = form_data.get(
137 137 'enable_statistics', defs.get('repo_enable_statistics'))
138 138 enable_locking = form_data.get(
139 139 'enable_locking', defs.get('repo_enable_locking'))
140 140 enable_downloads = form_data.get(
141 141 'enable_downloads', defs.get('repo_enable_downloads'))
142 142
143 143 try:
144 144 RepoModel(DBS)._create_repo(
145 145 repo_name=repo_name_full,
146 146 repo_type=repo_type,
147 147 description=description,
148 148 owner=owner,
149 149 private=private,
150 150 clone_uri=clone_uri,
151 151 repo_group=repo_group,
152 152 landing_rev=landing_rev,
153 153 fork_of=fork_of,
154 154 copy_fork_permissions=copy_fork_permissions,
155 155 copy_group_permissions=copy_group_permissions,
156 156 enable_statistics=enable_statistics,
157 157 enable_locking=enable_locking,
158 158 enable_downloads=enable_downloads,
159 159 state=state
160 160 )
161 161
162 162 action_logger(cur_user, 'user_created_repo',
163 163 repo_name_full, '', DBS)
164 164 DBS.commit()
165 165
166 166 # now create this repo on Filesystem
167 167 RepoModel(DBS)._create_filesystem_repo(
168 168 repo_name=repo_name,
169 169 repo_type=repo_type,
170 170 repo_group=RepoModel(DBS)._get_repo_group(repo_group),
171 171 clone_uri=clone_uri,
172 172 )
173 173 repo = Repository.get_by_repo_name(repo_name_full)
174 174 log_create_repository(created_by=owner.username, **repo.get_dict())
175 175
176 176 # update repo commit caches initially
177 177 repo.update_commit_cache()
178 178
179 179 # set new created state
180 180 repo.set_state(Repository.STATE_CREATED)
181 181 DBS.commit()
182 182 except Exception as e:
183 183 log.warning('Exception %s occurred when creating repository, '
184 184 'doing cleanup...', e)
185 185 # rollback things manually !
186 186 repo = Repository.get_by_repo_name(repo_name_full)
187 187 if repo:
188 188 Repository.delete(repo.repo_id)
189 189 DBS.commit()
190 190 RepoModel(DBS)._delete_filesystem_repo(repo)
191 191 raise
192 192
193 193 # it's an odd fix to make celery fail task when exception occurs
194 194 def on_failure(self, *args, **kwargs):
195 195 pass
196 196
197 197 return True
198 198
199 199
200 200 @task(ignore_result=False)
201 201 @dbsession
202 202 @vcsconnection
203 203 def create_repo_fork(form_data, cur_user):
204 204 """
205 205 Creates a fork of repository using internal VCS methods
206 206
207 207 :param form_data:
208 208 :param cur_user:
209 209 """
210 210 from rhodecode.model.repo import RepoModel
211 211 from rhodecode.model.user import UserModel
212 212
213 213 log = get_logger(create_repo_fork)
214 214 DBS = get_session()
215 215
216 216 cur_user = UserModel(DBS)._get_user(cur_user)
217 217 owner = cur_user
218 218
219 219 repo_name = form_data['repo_name'] # fork in this case
220 220 repo_name_full = form_data['repo_name_full']
221 221 repo_type = form_data['repo_type']
222 222 description = form_data['description']
223 223 private = form_data['private']
224 224 clone_uri = form_data.get('clone_uri')
225 225 repo_group = safe_int(form_data['repo_group'])
226 226 landing_rev = form_data['landing_rev']
227 227 copy_fork_permissions = form_data.get('copy_permissions')
228 228 fork_id = safe_int(form_data.get('fork_parent_id'))
229 229
230 230 try:
231 231 fork_of = RepoModel(DBS)._get_repo(fork_id)
232 232 RepoModel(DBS)._create_repo(
233 233 repo_name=repo_name_full,
234 234 repo_type=repo_type,
235 235 description=description,
236 236 owner=owner,
237 237 private=private,
238 238 clone_uri=clone_uri,
239 239 repo_group=repo_group,
240 240 landing_rev=landing_rev,
241 241 fork_of=fork_of,
242 242 copy_fork_permissions=copy_fork_permissions
243 243 )
244 244 action_logger(cur_user, 'user_forked_repo:%s' % repo_name_full,
245 245 fork_of.repo_name, '', DBS)
246 246 DBS.commit()
247 247
248 248 base_path = Repository.base_path()
249 249 source_repo_path = os.path.join(base_path, fork_of.repo_name)
250 250
251 251 # now create this repo on Filesystem
252 252 RepoModel(DBS)._create_filesystem_repo(
253 253 repo_name=repo_name,
254 254 repo_type=repo_type,
255 255 repo_group=RepoModel(DBS)._get_repo_group(repo_group),
256 256 clone_uri=source_repo_path,
257 257 )
258 258 repo = Repository.get_by_repo_name(repo_name_full)
259 259 log_create_repository(created_by=owner.username, **repo.get_dict())
260 260
261 261 # update repo commit caches initially
262 262 config = repo._config
263 263 config.set('extensions', 'largefiles', '')
264 264 repo.update_commit_cache(config=config)
265 265
266 266 # set new created state
267 267 repo.set_state(Repository.STATE_CREATED)
268 268 DBS.commit()
269 269 except Exception as e:
270 270 log.warning('Exception %s occurred when forking repository, '
271 271 'doing cleanup...', e)
272 272 # rollback things manually !
273 273 repo = Repository.get_by_repo_name(repo_name_full)
274 274 if repo:
275 275 Repository.delete(repo.repo_id)
276 276 DBS.commit()
277 277 RepoModel(DBS)._delete_filesystem_repo(repo)
278 278 raise
279 279
280 280 # it's an odd fix to make celery fail task when exception occurs
281 281 def on_failure(self, *args, **kwargs):
282 282 pass
283 283
284 284 return True
General Comments 0
You need to be logged in to leave comments. Login now