def update_perms(self, group_name): """ Update permissions for given repository group :param group_name: """ c.repo_group = RepoGroup.guess_instance(group_name) valid_recursive_choices = ['none', 'repos', 'groups', 'all'] form_result = RepoGroupPermsForm(valid_recursive_choices)().to_python(request.POST) if not request.authuser.is_admin: if self._revoke_perms_on_yourself(form_result): msg = _('Cannot revoke permission for yourself as admin') h.flash(msg, category='warning') raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name)) recursive = form_result['recursive'] # iterate over all members(if in recursive mode) of this groups and # set the permissions ! # this can be potentially heavy operation RepoGroupModel()._update_permissions(c.repo_group, form_result['perms_new'], form_result['perms_updates'], recursive) #TODO: implement this #action_logger(request.authuser, 'admin_changed_repo_permissions', # repo_name, request.ip_addr) Session().commit() h.flash(_('Repository group permissions updated'), category='success') raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name))
def grant_user_group_permission(self, repo_group, group_name, perm): """ Grant permission for user group on given repository group, or update existing one if found :param repo_group: Instance of RepoGroup, repositories_group_id, or repositories_group name :param group_name: Instance of UserGroup, users_group_id, or user group name :param perm: Instance of Permission, or permission_name """ repo_group = RepoGroup.guess_instance(repo_group) group_name = UserGroup.guess_instance(group_name) permission = Permission.guess_instance(perm) # check if we have that permission already obj = UserGroupRepoGroupToPerm.query() \ .filter(UserGroupRepoGroupToPerm.group == repo_group) \ .filter(UserGroupRepoGroupToPerm.users_group == group_name) \ .scalar() if obj is None: # create new obj = UserGroupRepoGroupToPerm() Session().add(obj) obj.group = repo_group obj.users_group = group_name obj.permission = permission log.debug('Granted perm %s to %s on %s', perm, group_name, repo_group) return obj
def update_perms(self, group_name): """ Update permissions for given repository group :param group_name: """ c.repo_group = RepoGroup.guess_instance(group_name) valid_recursive_choices = ['none', 'repos', 'groups', 'all'] form_result = RepoGroupPermsForm(valid_recursive_choices)().to_python( request.POST) if not request.authuser.is_admin: if self._revoke_perms_on_yourself(form_result): msg = _('Cannot revoke permission for yourself as admin') h.flash(msg, category='warning') raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name)) recursive = form_result['recursive'] # iterate over all members(if in recursive mode) of this groups and # set the permissions ! # this can be potentially heavy operation RepoGroupModel()._update_permissions(c.repo_group, form_result['perms_new'], form_result['perms_updates'], recursive) #TODO: implement this #action_logger(request.authuser, 'admin_changed_repo_permissions', # repo_name, request.ip_addr) Session().commit() h.flash(_('Repository group permissions updated'), category='success') raise HTTPFound( location=url('edit_repo_group_perms', group_name=group_name))
def delete(self, group_name): gr = c.repo_group = RepoGroup.guess_instance(group_name) repos = gr.repositories.all() if repos: h.flash(_('This group contains %s repositories and cannot be ' 'deleted') % len(repos), category='warning') raise HTTPFound(location=url('repos_groups')) children = gr.children.all() if children: h.flash( _('This group contains %s subgroups and cannot be deleted' % (len(children))), category='warning') raise HTTPFound(location=url('repos_groups')) try: RepoGroupModel().delete(group_name) Session().commit() h.flash(_('Removed repository group %s') % group_name, category='success') #TODO: in future action_logger(, '', '', '') except Exception: log.error(traceback.format_exc()) h.flash( _('Error occurred during deletion of repository group %s') % group_name, category='error') if gr.parent_group: raise HTTPFound(location=url( 'repos_group_home', group_name=gr.parent_group.group_name)) raise HTTPFound(location=url('repos_groups'))
def delete(self, group_name): gr = c.repo_group = RepoGroup.guess_instance(group_name) repos = gr.repositories.all() if repos: h.flash(_('This group contains %s repositories and cannot be ' 'deleted') % len(repos), category='warning') raise HTTPFound(location=url('repos_groups')) children = gr.children.all() if children: h.flash(_('This group contains %s subgroups and cannot be deleted' % (len(children))), category='warning') raise HTTPFound(location=url('repos_groups')) try: RepoGroupModel().delete(group_name) Session().commit() h.flash(_('Removed repository group %s') % group_name, category='success') #TODO: in future action_logger(, '', '', '') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during deletion of repository group %s') % group_name, category='error') if gr.parent_group: raise HTTPFound(location=url('repos_group_home', group_name=gr.parent_group.group_name)) raise HTTPFound(location=url('repos_groups'))
def delete(self, repo_group, force_delete=False): repo_group = RepoGroup.guess_instance(repo_group) try: Session().delete(repo_group) self._delete_group(repo_group, force_delete) except Exception: log.error('Error removing repo_group %s', repo_group) raise
def edit_repo_group_perms(self, group_name): c.active = 'perms' c.repo_group = RepoGroup.guess_instance(group_name) self.__load_defaults() defaults = self.__load_data(c.repo_group.group_id) return htmlfill.render( render('admin/repo_groups/repo_group_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def edit_repo_group_perms(self, group_name): c.active = 'perms' c.repo_group = RepoGroup.guess_instance(group_name) self.__load_defaults() defaults = self.__load_data(c.repo_group.group_id) return htmlfill.render( render('admin/repo_groups/repo_group_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False )
def delete_permission(self, repo_group, obj, obj_type, recursive): """ Revokes permission for repo_group for given obj(user or users_group), obj_type can be user or user group :param repo_group: :param obj: user or user group id :param obj_type: user or user group type :param recursive: recurse to all children of group """ from kallithea.model.repo import RepoModel repo_group = RepoGroup.guess_instance(repo_group) for el in repo_group.recursive_groups_and_repos(): # iterated obj is an instance of a repos group or repository in # that group, recursive option can be: none, repos, groups, all if recursive == 'all': pass elif recursive == 'repos': # skip groups, other than this one if isinstance(el, RepoGroup) and not el == repo_group: continue elif recursive == 'groups': # skip repos if isinstance(el, Repository): continue else: # recursive == 'none': # DEFAULT don't apply to iterated objects el = repo_group # also we do a break at the end of this loop. if isinstance(el, RepoGroup): if obj_type == 'user': RepoGroupModel().revoke_user_permission(el, user=obj) elif obj_type == 'user_group': RepoGroupModel().revoke_user_group_permission(el, group_name=obj) else: raise Exception('undefined object type %s' % obj_type) elif isinstance(el, Repository): if obj_type == 'user': RepoModel().revoke_user_permission(el, user=obj) elif obj_type == 'user_group': RepoModel().revoke_user_group_permission(el, group_name=obj) else: raise Exception('undefined object type %s' % obj_type) else: raise Exception('el should be instance of Repository or ' 'RepositoryGroup got %s instead' % type(el)) # if it's not recursive call for all,repos,groups # break the loop and don't proceed with other changes if recursive not in ['all', 'repos', 'groups']: break
def edit(self, group_name): c.active = 'settings' c.repo_group = RepoGroup.guess_instance(group_name) self.__load_defaults(extras=[c.repo_group.parent_group], exclude=[c.repo_group]) defaults = self.__load_data(c.repo_group.group_id) return htmlfill.render( render('admin/repo_groups/repo_group_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def edit(self, group_name): c.active = 'settings' c.repo_group = RepoGroup.guess_instance(group_name) self.__load_defaults(extras=[c.repo_group.parent_group], exclude=[c.repo_group]) defaults = self.__load_data(c.repo_group.group_id) return htmlfill.render( render('admin/repo_groups/repo_group_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False )
def show(self, group_name): c.active = 'settings' c.group = c.repo_group = RepoGroup.guess_instance(group_name) groups = RepoGroup.query(sorted=True).filter_by(parent_group=c.group).all() repo_groups_list = self.scm_model.get_repo_groups(groups) repos_list = Repository.query(sorted=True).filter_by(group=c.group).all() c.data = RepoModel().get_repos_as_dict(repos_list, repo_groups_list=repo_groups_list, short_name=True) return render('admin/repo_groups/repo_group_show.html')
def create(self, group_name, group_description, owner, parent=None, just_db=False, copy_permissions=False): try: owner = User.guess_instance(owner) parent_group = RepoGroup.guess_instance(parent) new_repo_group = RepoGroup() new_repo_group.owner = owner new_repo_group.group_description = group_description or group_name new_repo_group.parent_group = parent_group new_repo_group.group_name = new_repo_group.get_new_name(group_name) Session().add(new_repo_group) # create an ADMIN permission for owner except if we're super admin, # later owner should go into the owner field of groups if not owner.is_admin: self.grant_user_permission(repo_group=new_repo_group, user=owner, perm='group.admin') if parent_group and copy_permissions: # copy permissions from parent user_perms = UserRepoGroupToPerm.query() \ .filter(UserRepoGroupToPerm.group == parent_group).all() group_perms = UserGroupRepoGroupToPerm.query() \ .filter(UserGroupRepoGroupToPerm.group == parent_group).all() for perm in user_perms: # don't copy over the permission for user who is creating # this group, if he is not super admin he get's admin # permission set above if perm.user != owner or owner.is_admin: UserRepoGroupToPerm.create(perm.user, new_repo_group, perm.permission) for perm in group_perms: UserGroupRepoGroupToPerm.create(perm.users_group, new_repo_group, perm.permission) else: self._create_default_perms(new_repo_group) if not just_db: # we need to flush here, in order to check if database won't # throw any exceptions, create filesystem dirs at the very end Session().flush() self._create_group(new_repo_group.group_name) return new_repo_group except Exception: log.error(traceback.format_exc()) raise
def update(self, repo_group, kwargs): try: repo_group = RepoGroup.guess_instance(repo_group) old_path = repo_group.full_path # change properties if 'group_description' in kwargs: repo_group.group_description = kwargs['group_description'] if 'parent_group_id' in kwargs: repo_group.parent_group_id = kwargs['parent_group_id'] if 'enable_locking' in kwargs: repo_group.enable_locking = kwargs['enable_locking'] if 'parent_group_id' in kwargs: assert kwargs['parent_group_id'] != u'-1', kwargs # RepoGroupForm should have converted to None repo_group.parent_group = RepoGroup.get(kwargs['parent_group_id']) if 'group_name' in kwargs: repo_group.group_name = repo_group.get_new_name(kwargs['group_name']) new_path = repo_group.full_path Session().add(repo_group) # iterate over all members of this groups and do fixes # set locking if given # if obj is a repoGroup also fix the name of the group according # to the parent # if obj is a Repo fix it's name # this can be potentially heavy operation for obj in repo_group.recursive_groups_and_repos(): #set the value from it's parent obj.enable_locking = repo_group.enable_locking if isinstance(obj, RepoGroup): new_name = obj.get_new_name(obj.name) log.debug('Fixing group %s to new name %s' \ % (obj.group_name, new_name)) obj.group_name = new_name elif isinstance(obj, Repository): # we need to get all repositories from this new group and # rename them accordingly to new group path new_name = obj.get_new_name(obj.just_name) log.debug('Fixing repo %s to new name %s' \ % (obj.repo_name, new_name)) obj.repo_name = new_name self._rename_group(old_path, new_path) return repo_group except Exception: log.error(traceback.format_exc()) raise
def show(self, group_name): c.active = 'settings' c.group = c.repo_group = RepoGroup.guess_instance(group_name) groups = RepoGroup.query(sorted=True).filter_by(parent_group=c.group).all() c.groups = self.scm_model.get_repo_groups(groups) repos_list = Repository.query(sorted=True).filter_by(group=c.group).all() repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, admin=False, short_name=True) # data used to render the grid c.data = repos_data return render('admin/repo_groups/repo_group_show.html')
def add_permission(self, repo_group, obj, obj_type, perm, recursive): from kallithea.model.repo import RepoModel repo_group = RepoGroup.guess_instance(repo_group) perm = Permission.guess_instance(perm) for el in repo_group.recursive_groups_and_repos(): # iterated obj is an instance of a repos group or repository in # that group, recursive option can be: none, repos, groups, all if recursive == 'all': pass elif recursive == 'repos': # skip groups, other than this one if isinstance(el, RepoGroup) and not el == repo_group: continue elif recursive == 'groups': # skip repos if isinstance(el, Repository): continue else: # recursive == 'none': # DEFAULT don't apply to iterated objects el = repo_group # also we do a break at the end of this loop. if isinstance(el, RepoGroup): if obj_type == 'user': RepoGroupModel().grant_user_permission(el, user=obj, perm=perm) elif obj_type == 'user_group': RepoGroupModel().grant_user_group_permission(el, group_name=obj, perm=perm) else: raise Exception('undefined object type %s' % obj_type) elif isinstance(el, Repository): # for repos we need to hotfix the name of permission _perm = perm.permission_name.replace('group.', 'repository.') if obj_type == 'user': RepoModel().grant_user_permission(el, user=obj, perm=_perm) elif obj_type == 'user_group': RepoModel().grant_user_group_permission(el, group_name=obj, perm=_perm) else: raise Exception('undefined object type %s' % obj_type) else: raise Exception('el should be instance of Repository or ' 'RepositoryGroup got %s instead' % type(el)) # if it's not recursive call for all,repos,groups # break the loop and don't proceed with other changes if recursive not in ['all', 'repos', 'groups']: break
def update(self, group_name): c.repo_group = RepoGroup.guess_instance(group_name) self.__load_defaults(extras=[c.repo_group.parent_group], exclude=[c.repo_group]) # TODO: kill allow_empty_group - it is only used for redundant form validation! if HasPermissionAny('hg.admin')('group edit'): #we're global admin, we're ok and we can create TOP level groups allow_empty_group = True elif not c.repo_group.parent_group: allow_empty_group = True else: allow_empty_group = False repo_group_form = RepoGroupForm( edit=True, old_data=c.repo_group.get_dict(), repo_groups=c.repo_groups, can_create_in_root=allow_empty_group, )() try: form_result = repo_group_form.to_python(dict(request.POST)) new_gr = RepoGroupModel().update(group_name, form_result) Session().commit() h.flash(_('Updated repository group %s') \ % form_result['group_name'], category='success') # we now have new name ! group_name = new_gr.group_name #TODO: in future action_logger(, '', '', '') except formencode.Invalid as errors: c.active = 'settings' return htmlfill.render( render('admin/repo_groups/repo_group_edit.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of repository group %s') \ % request.POST.get('group_name'), category='error') raise HTTPFound(location=url('edit_repo_group', group_name=group_name))
def revoke_user_group_permission(self, repo_group, group_name): """ Revoke permission for user group on given repository group :param repo_group: Instance of RepoGroup, repositories_group_id, or repositories_group name :param group_name: Instance of UserGroup, users_group_id, or user group name """ repo_group = RepoGroup.guess_instance(repo_group) group_name = UserGroup.guess_instance(group_name) obj = UserGroupRepoGroupToPerm.query() \ .filter(UserGroupRepoGroupToPerm.group == repo_group) \ .filter(UserGroupRepoGroupToPerm.users_group == group_name) \ .scalar() if obj is not None: Session().delete(obj) log.debug('Revoked perm to %s on %s', repo_group, group_name)
def revoke_user_permission(self, repo_group, user): """ Revoke permission for user on given repository group :param repo_group: Instance of RepoGroup, repositories_group_id, or repositories_group name :param user: Instance of User, user_id or username """ repo_group = RepoGroup.guess_instance(repo_group) user = User.guess_instance(user) obj = UserRepoGroupToPerm.query() \ .filter(UserRepoGroupToPerm.user == user) \ .filter(UserRepoGroupToPerm.group == repo_group) \ .scalar() if obj is not None: Session().delete(obj) log.debug('Revoked perm on %s on %s', repo_group, user)
def _create_repo(self, repo_name, repo_type, description, owner, private=False, clone_uri=None, repo_group=None, landing_rev='rev:tip', fork_of=None, copy_fork_permissions=False, enable_statistics=False, enable_locking=False, enable_downloads=False, copy_group_permissions=False, state=Repository.STATE_PENDING): """ Create repository inside database with PENDING state. This should only be executed by create() repo, with exception of importing existing repos. """ from kallithea.model.scm import ScmModel owner = User.guess_instance(owner) fork_of = Repository.guess_instance(fork_of) repo_group = RepoGroup.guess_instance(repo_group) try: repo_name = safe_unicode(repo_name) description = safe_unicode(description) # repo name is just a name of repository # while repo_name_full is a full qualified name that is combined # with name and path of group repo_name_full = repo_name repo_name = repo_name.split(self.URL_SEPARATOR)[-1] new_repo = Repository() new_repo.repo_state = state new_repo.enable_statistics = False new_repo.repo_name = repo_name_full new_repo.repo_type = repo_type new_repo.owner = owner new_repo.group = repo_group new_repo.description = description or repo_name new_repo.private = private new_repo.clone_uri = clone_uri new_repo.landing_rev = landing_rev new_repo.enable_statistics = enable_statistics new_repo.enable_locking = enable_locking new_repo.enable_downloads = enable_downloads if repo_group: new_repo.enable_locking = repo_group.enable_locking if fork_of: parent_repo = fork_of new_repo.fork = parent_repo Session().add(new_repo) if fork_of and copy_fork_permissions: repo = fork_of user_perms = UserRepoToPerm.query() \ .filter(UserRepoToPerm.repository == repo).all() group_perms = UserGroupRepoToPerm.query() \ .filter(UserGroupRepoToPerm.repository == repo).all() for perm in user_perms: UserRepoToPerm.create(perm.user, new_repo, perm.permission) for perm in group_perms: UserGroupRepoToPerm.create(perm.users_group, new_repo, perm.permission) elif repo_group and copy_group_permissions: user_perms = UserRepoGroupToPerm.query() \ .filter(UserRepoGroupToPerm.group == repo_group).all() group_perms = UserGroupRepoGroupToPerm.query() \ .filter(UserGroupRepoGroupToPerm.group == repo_group).all() for perm in user_perms: perm_name = perm.permission.permission_name.replace( 'group.', 'repository.') perm_obj = Permission.get_by_key(perm_name) UserRepoToPerm.create(perm.user, new_repo, perm_obj) for perm in group_perms: perm_name = perm.permission.permission_name.replace( 'group.', 'repository.') perm_obj = Permission.get_by_key(perm_name) UserGroupRepoToPerm.create(perm.users_group, new_repo, perm_obj) else: self._create_default_perms(new_repo, private) # now automatically start following this repository as owner ScmModel().toggle_following_repo(new_repo.repo_id, owner.user_id) # we need to flush here, in order to check if database won't # throw any exceptions, create filesystem dirs at the very end Session().flush() return new_repo except Exception: log.error(traceback.format_exc()) raise
def edit_repo_group_advanced(self, group_name): c.active = 'advanced' c.repo_group = RepoGroup.guess_instance(group_name) return render('admin/repo_groups/repo_group_edit.html')
def _create_repo(self, repo_name, repo_type, description, owner, private=False, clone_uri=None, repo_group=None, landing_rev='rev:tip', fork_of=None, copy_fork_permissions=False, enable_statistics=False, enable_locking=False, enable_downloads=False, copy_group_permissions=False, state=Repository.STATE_PENDING): """ Create repository inside database with PENDING state. This should only be executed by create() repo, with exception of importing existing repos. """ from kallithea.model.scm import ScmModel owner = User.guess_instance(owner) fork_of = Repository.guess_instance(fork_of) repo_group = RepoGroup.guess_instance(repo_group) try: repo_name = safe_unicode(repo_name) description = safe_unicode(description) # repo name is just a name of repository # while repo_name_full is a full qualified name that is combined # with name and path of group repo_name_full = repo_name repo_name = repo_name.split(self.URL_SEPARATOR)[-1] new_repo = Repository() new_repo.repo_state = state new_repo.enable_statistics = False new_repo.repo_name = repo_name_full new_repo.repo_type = repo_type new_repo.owner = owner new_repo.group = repo_group new_repo.description = description or repo_name new_repo.private = private new_repo.clone_uri = clone_uri new_repo.landing_rev = landing_rev new_repo.enable_statistics = enable_statistics new_repo.enable_locking = enable_locking new_repo.enable_downloads = enable_downloads if repo_group: new_repo.enable_locking = repo_group.enable_locking if fork_of: parent_repo = fork_of new_repo.fork = parent_repo Session().add(new_repo) if fork_of and copy_fork_permissions: repo = fork_of user_perms = UserRepoToPerm.query() \ .filter(UserRepoToPerm.repository == repo).all() group_perms = UserGroupRepoToPerm.query() \ .filter(UserGroupRepoToPerm.repository == repo).all() for perm in user_perms: UserRepoToPerm.create(perm.user, new_repo, perm.permission) for perm in group_perms: UserGroupRepoToPerm.create(perm.users_group, new_repo, perm.permission) elif repo_group and copy_group_permissions: user_perms = UserRepoGroupToPerm.query() \ .filter(UserRepoGroupToPerm.group == repo_group).all() group_perms = UserGroupRepoGroupToPerm.query() \ .filter(UserGroupRepoGroupToPerm.group == repo_group).all() for perm in user_perms: perm_name = perm.permission.permission_name.replace('group.', 'repository.') perm_obj = Permission.get_by_key(perm_name) UserRepoToPerm.create(perm.user, new_repo, perm_obj) for perm in group_perms: perm_name = perm.permission.permission_name.replace('group.', 'repository.') perm_obj = Permission.get_by_key(perm_name) UserGroupRepoToPerm.create(perm.users_group, new_repo, perm_obj) else: self._create_default_perms(new_repo, private) # now automatically start following this repository as owner ScmModel().toggle_following_repo(new_repo.repo_id, owner.user_id) # we need to flush here, in order to check if database won't # throw any exceptions, create filesystem dirs at the very end Session().flush() return new_repo except Exception: log.error(traceback.format_exc()) raise
def create_repo(form_data, cur_user): from kallithea.model.repo import RepoModel from kallithea.model.db import Setting DBS = celerylib.get_session() cur_user = User.guess_instance(cur_user) owner = cur_user repo_name = form_data['repo_name'] repo_name_full = form_data['repo_name_full'] repo_type = form_data['repo_type'] description = form_data['repo_description'] private = form_data['repo_private'] clone_uri = form_data.get('clone_uri') repo_group = form_data['repo_group'] landing_rev = form_data['repo_landing_rev'] copy_fork_permissions = form_data.get('copy_permissions') copy_group_permissions = form_data.get('repo_copy_permissions') fork_of = form_data.get('fork_parent_id') state = form_data.get('repo_state', Repository.STATE_PENDING) # repo creation defaults, private and repo_type are filled in form defs = Setting.get_default_repo_settings(strip_prefix=True) enable_statistics = defs.get('repo_enable_statistics') enable_downloads = defs.get('repo_enable_downloads') try: repo = RepoModel()._create_repo( repo_name=repo_name_full, repo_type=repo_type, description=description, owner=owner, private=private, clone_uri=clone_uri, repo_group=repo_group, landing_rev=landing_rev, fork_of=fork_of, copy_fork_permissions=copy_fork_permissions, copy_group_permissions=copy_group_permissions, enable_statistics=enable_statistics, enable_downloads=enable_downloads, state=state) action_logger(cur_user, 'user_created_repo', form_data['repo_name_full'], '') DBS.commit() # now create this repo on Filesystem RepoModel()._create_filesystem_repo( repo_name=repo_name, repo_type=repo_type, repo_group=RepoGroup.guess_instance(repo_group), clone_uri=clone_uri, ) repo = Repository.get_by_repo_name(repo_name_full) log_create_repository(repo.get_dict(), created_by=owner.username) # update repo changeset caches initially repo.update_changeset_cache() # set new created state repo.set_state(Repository.STATE_CREATED) DBS.commit() except Exception as e: log.warning('Exception %s occurred when forking repository, ' 'doing cleanup...' % e) # rollback things manually ! repo = Repository.get_by_repo_name(repo_name_full) if repo: Repository.delete(repo.repo_id) DBS.commit() RepoModel()._delete_filesystem_repo(repo) raise return True
def create_repo_fork(form_data, cur_user): """ Creates a fork of repository using interval VCS methods :param form_data: :param cur_user: """ from kallithea.model.repo import RepoModel DBS = celerylib.get_session() base_path = kallithea.CONFIG['base_path'] cur_user = User.guess_instance(cur_user) repo_name = form_data['repo_name'] # fork in this case repo_name_full = form_data['repo_name_full'] repo_type = form_data['repo_type'] owner = cur_user private = form_data['private'] clone_uri = form_data.get('clone_uri') repo_group = form_data['repo_group'] landing_rev = form_data['landing_rev'] copy_fork_permissions = form_data.get('copy_permissions') try: fork_of = Repository.guess_instance(form_data.get('fork_parent_id')) RepoModel()._create_repo(repo_name=repo_name_full, repo_type=repo_type, description=form_data['description'], owner=owner, private=private, clone_uri=clone_uri, repo_group=repo_group, landing_rev=landing_rev, fork_of=fork_of, copy_fork_permissions=copy_fork_permissions) action_logger(cur_user, 'user_forked_repo:%s' % repo_name_full, fork_of.repo_name, '') DBS.commit() source_repo_path = os.path.join(base_path, fork_of.repo_name) # now create this repo on Filesystem RepoModel()._create_filesystem_repo( repo_name=repo_name, repo_type=repo_type, repo_group=RepoGroup.guess_instance(repo_group), clone_uri=source_repo_path, ) repo = Repository.get_by_repo_name(repo_name_full) log_create_repository(repo.get_dict(), created_by=owner.username) # update repo changeset caches initially repo.update_changeset_cache() # set new created state repo.set_state(Repository.STATE_CREATED) DBS.commit() except Exception as e: log.warning('Exception %s occurred when forking repository, ' 'doing cleanup...' % e) # rollback things manually ! repo = Repository.get_by_repo_name(repo_name_full) if repo: Repository.delete(repo.repo_id) DBS.commit() RepoModel()._delete_filesystem_repo(repo) raise return True