def delete(self, repo_name): repo_model = RepoModel() repo = repo_model.get_by_repo_name(repo_name) if not repo: h.not_mapped_error(repo_name) raise HTTPFound(location=url('repos')) try: _forks = repo.forks.count() handle_forks = None if _forks and request.POST.get('forks'): do = request.POST['forks'] if do == 'detach_forks': handle_forks = 'detach' h.flash(_('Detached %s forks') % _forks, category='success') elif do == 'delete_forks': handle_forks = 'delete' h.flash(_('Deleted %s forks') % _forks, category='success') repo_model.delete(repo, forks=handle_forks) action_logger(request.authuser, 'admin_deleted_repo', repo_name, request.ip_addr) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Deleted repository %s') % repo_name, category='success') Session().commit() except AttachedForksError: h.flash(_('Cannot delete repository %s which still has forks') % repo_name, category='warning') except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during deletion of %s') % repo_name, category='error') if repo.group: raise HTTPFound(location=url('repos_group_home', group_name=repo.group.group_name)) raise HTTPFound(location=url('repos'))
def update(self, repo_name): """ PUT /repos/repo_name: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('put_repo', repo_name=ID), # method='put') # url('put_repo', repo_name=ID) c.repo_info = self._load_repo(repo_name) self.__load_defaults(c.repo_info) c.active = 'settings' c.repo_fields = RepositoryField.query() \ .filter(RepositoryField.repository == c.repo_info).all() repo_model = RepoModel() changed_name = repo_name repo = Repository.get_by_repo_name(repo_name) old_data = { 'repo_name': repo_name, 'repo_group': repo.group.get_dict() if repo.group else {}, 'repo_type': repo.repo_type, } _form = RepoForm(edit=True, old_data=old_data, repo_groups=c.repo_groups, landing_revs=c.landing_revs_choices)() try: form_result = _form.to_python(dict(request.POST)) repo = repo_model.update(repo_name, **form_result) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Repository %s updated successfully') % repo_name, category='success') changed_name = repo.repo_name action_logger(self.authuser, 'admin_updated_repo', changed_name, self.ip_addr, self.sa) Session().commit() except formencode.Invalid as errors: log.info(errors) defaults = self.__load_data(repo_name) defaults.update(errors.value) c.users_array = repo_model.get_users_js() return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, 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 %s') \ % repo_name, category='error') raise HTTPFound(location=url('edit_repo', repo_name=changed_name))
def edit(self, repo_name): defaults = self.__load_data() c.repo_fields = RepositoryField.query() \ .filter(RepositoryField.repository == c.repo_info).all() repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.active = 'settings' return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def edit_permissions(self, repo_name): c.repo_info = self._load_repo() repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.user_groups_array = repo_model.get_user_groups_js() c.active = 'permissions' defaults = RepoModel()._get_defaults(repo_name) return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def __load_defaults(self, extras=(), exclude=()): """extras is used for keeping current parent ignoring permissions exclude is used for not moving group to itself TODO: also exclude descendants Note: only admin can create top level groups """ repo_groups = AvailableRepoGroupChoices([], 'admin', extras) exclude_group_ids = set(rg.group_id for rg in exclude) c.repo_groups = [rg for rg in repo_groups if rg[0] not in exclude_group_ids] repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.user_groups_array = repo_model.get_user_groups_js()
def edit(self, repo_name): """GET /repo_name/settings: Form to edit an existing item""" # url('edit_repo', repo_name=ID) defaults = self.__load_data(repo_name) c.repo_fields = RepositoryField.query() \ .filter(RepositoryField.repository == c.repo_info).all() repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.active = 'settings' return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def edit_permissions(self, repo_name): """GET /repo_name/settings: Form to edit an existing item""" # url('edit_repo', repo_name=ID) c.repo_info = self._load_repo(repo_name) repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.user_groups_array = repo_model.get_user_groups_js() c.active = 'permissions' defaults = RepoModel()._get_defaults(repo_name) return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def __load_defaults(self, allow_empty_group=False, exclude_group_ids=[]): if HasPermissionAll('hg.admin')('group edit'): #we're global admin, we're ok and we can create TOP level groups allow_empty_group = True #override the choices for this form, we need to filter choices #and display only those we have ADMIN right groups_with_admin_rights = RepoGroupList(RepoGroup.query().all(), perm_set=['group.admin']) c.repo_groups = RepoGroup.groups_choices(groups=groups_with_admin_rights, show_empty_group=allow_empty_group) # exclude filtered ids c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids, c.repo_groups) c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.user_groups_array = repo_model.get_user_groups_js()
def delete(self, repo_name): """ DELETE /repos/repo_name: Delete an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="DELETE" /> # Or using helpers: # h.form(url('repo', repo_name=ID), # method='delete') # url('repo', repo_name=ID) repo_model = RepoModel() repo = repo_model.get_by_repo_name(repo_name) if not repo: h.not_mapped_error(repo_name) return redirect(url('repos')) try: _forks = repo.forks.count() handle_forks = None if _forks and request.POST.get('forks'): do = request.POST['forks'] if do == 'detach_forks': handle_forks = 'detach' h.flash(_('Detached %s forks') % _forks, category='success') elif do == 'delete_forks': handle_forks = 'delete' h.flash(_('Deleted %s forks') % _forks, category='success') repo_model.delete(repo, forks=handle_forks) action_logger(self.authuser, 'admin_deleted_repo', repo_name, self.ip_addr, self.sa) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Deleted repository %s') % repo_name, category='success') Session().commit() except AttachedForksError: h.flash(_('Cannot delete %s it still contains attached forks') % repo_name, category='warning') except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during deletion of %s') % repo_name, category='error') if repo.group: return redirect(url('repos_group_home', group_name=repo.group.group_name)) return redirect(url('repos'))
def command(self): #get SqlAlchemy session self._init_session() repo_update_list = map(string.strip, self.options.repo_update_list.split(',')) \ if self.options.repo_update_list else None if repo_update_list: repo_list = list(Repository.query()\ .filter(Repository.repo_name.in_(repo_update_list))) else: repo_list = Repository.getAll() RepoModel.update_repoinfo(repositories=repo_list) Session().commit() if self.options.invalidate_cache: for r in repo_list: r.set_invalidate() print 'Updated cache for %s repositories' % (len(repo_list))
def index(self): c.groups = self.scm_model.get_repo_groups() c.group = None repos_list = Repository.query(sorted=True).filter_by(group=None).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('/index.html')
def _destroy_project_tree(test_u1_id): Session.remove() repo_group = RepoGroup.get_by_group_name(group_name=u'g0') for el in reversed(repo_group.recursive_groups_and_repos()): if isinstance(el, Repository): RepoModel().delete(el) elif isinstance(el, RepoGroup): RepoGroupModel().delete(el, force_delete=True) u = User.get(test_u1_id) Session().delete(u) Session().commit()
def test_default_perms_set(self): u1_auth = AuthUser(user_id=self.u1.user_id) assert u1_auth.permissions['repositories'][ base.HG_REPO] == 'repository.read' new_perm = 'repository.write' RepoModel().grant_user_permission(repo=base.HG_REPO, user=self.u1, perm=new_perm) Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) assert u1_auth.permissions['repositories'][base.HG_REPO] == new_perm
def __load_data(self): """ Load defaults settings for edit, and update """ c.repo_info = self._load_repo() self.__load_defaults(c.repo_info) defaults = RepoModel()._get_defaults(c.repo_name) defaults[ 'clone_uri'] = c.repo_info.clone_uri_hidden # don't show password return defaults
def test_index_page_on_groups(self): self.log_user() gr = fixture.create_repo_group('gr1') fixture.create_repo(name='gr1/repo_in_group', repo_group=gr) response = self.app.get(url('repos_group_home', group_name='gr1')) try: response.mustcontain("gr1/repo_in_group") finally: RepoModel().delete('gr1/repo_in_group') RepoGroupModel().delete(repo_group='gr1', force_delete=True) Session().commit()
def _set_perm_group(obj, users_group, perm): if isinstance(obj, RepoGroup): self.grant_user_group_permission(repo_group=obj, group_name=users_group, perm=perm) elif isinstance(obj, Repository): # we set group permission but we have to switch to repo # permission perm = perm.replace('group.', 'repository.') RepoModel().grant_user_group_permission(repo=obj, group_name=users_group, perm=perm)
def test_propagated_permission_from_users_group(self): # make group self.ug1 = fixture.create_user_group('G1') UserGroupModel().add_user_to_group(self.ug1, self.u3) # grant perm for group this should override default permission from user new_perm_gr = 'repository.write' RepoModel().grant_user_group_permission(repo=base.HG_REPO, group_name=self.ug1, perm=new_perm_gr) # check perms u3_auth = AuthUser(user_id=self.u3.user_id) assert u3_auth.permissions['repositories'][base.HG_REPO] == new_perm_gr
def test_propagated_permission_from_users_group_lower_weight(self): # make group self.ug1 = fixture.create_user_group('G1') # add user to group UserGroupModel().add_user_to_group(self.ug1, self.u1) # set permission to lower new_perm_h = 'repository.write' RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm_h) Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], new_perm_h) # grant perm for group this should NOT override permission from user # since it's lower than granted new_perm_l = 'repository.read' RepoModel().grant_user_group_permission(repo=HG_REPO, group_name=self.ug1, perm=new_perm_l) # check perms u1_auth = AuthUser(user_id=self.u1.user_id) perms = { 'repositories_groups': {}, 'global': set([ u'hg.create.repository', u'repository.read', u'hg.register.manual_activate' ]), 'repositories': { u'vcs_test_hg': u'repository.write' } } self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], new_perm_h) self.assertEqual(u1_auth.permissions['repositories_groups'], perms['repositories_groups'])
def test_default_admin_perms_set(self): a1_auth = AuthUser(user_id=self.a1.user_id) assert a1_auth.permissions['repositories'][ base.HG_REPO] == 'repository.admin' new_perm = 'repository.write' RepoModel().grant_user_permission(repo=base.HG_REPO, user=self.a1, perm=new_perm) Session().commit() # cannot really downgrade admins permissions !? they still gets set as # admin ! u1_auth = AuthUser(user_id=self.a1.user_id) assert u1_auth.permissions['repositories'][ base.HG_REPO] == 'repository.admin'
def teardown_class(cls): # delete in reversed order, to delete fork destination at first for reponame, init_or_fork, groupname in reversed(repos): RepoModel().delete(repoids[reponame]) for reponame, init_or_fork, groupname in reversed(repos): if groupname in groupids: RepoGroupModel().delete(groupids.pop(groupname), force_delete=True) Session().commit() Session.remove() rebuild_index(full_index=True) # rebuild fully for subsequent tests
def create_test_repo(force=True): print 'creating test repo' from kallithea.model.repo import RepoModel sa = get_session() user = sa.query(User).filter(User.username == USER).scalar() if user is None: raise Exception('user not found') repo = sa.query(Repository).filter(Repository.repo_name == HG_REPO).scalar() if repo is None: print 'repo not found creating' form_data = {'repo_name': HG_REPO, 'repo_type': 'hg', 'private':False, 'clone_uri': '' } rm = RepoModel(sa) rm.base_path = '/home/hg' rm.create(form_data, user) print 'done'
def __load_data(self): """ Load defaults settings for edit, and update """ c.repo_info = self._load_repo() self.__load_defaults(c.repo_info) defaults = RepoModel()._get_defaults(c.repo_name) defaults[ 'clone_uri'] = c.repo_info.clone_uri_hidden # don't show password defaults['permanent_url'] = c.repo_info.clone_url( clone_uri_tmpl=c.clone_uri_tmpl, with_id=True) return defaults
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 edit_permissions_revoke(self, repo_name): try: obj_type = request.POST.get('obj_type') obj_id = None if obj_type == 'user': obj_id = safe_int(request.POST.get('user_id')) elif obj_type == 'user_group': obj_id = safe_int(request.POST.get('user_group_id')) if obj_type == 'user': RepoModel().revoke_user_permission(repo=repo_name, user=obj_id) elif obj_type == 'user_group': RepoModel().revoke_user_group_permission(repo=repo_name, group_name=obj_id) #TODO: implement this #action_logger(request.authuser, 'admin_revoked_repo_permissions', # repo_name, request.ip_addr) Session().commit() except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during revoking of permission'), category='error') raise HTTPInternalServerError()
def _load_my_repos_data(self, watched=False): if watched: admin = False repos_list = Session().query(Repository) \ .join(UserFollowing) \ .filter(UserFollowing.user_id == request.authuser.user_id).all() else: admin = True repos_list = Session().query(Repository) \ .filter(Repository.owner_id == request.authuser.user_id).all() return RepoModel().get_repos_as_dict(repos_list, admin=admin)
def test_propagated_permission_from_users_group_by_explicit_perms_exist( self): # make group self.ug1 = fixture.create_user_group(u'G1') UserGroupModel().add_user_to_group(self.ug1, self.u1) # set permission to lower new_perm = 'repository.none' RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm) Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) assert u1_auth.permissions['repositories'][HG_REPO] == new_perm # grant perm for group this should not override permission from user # since it has explicitly set new_perm_gr = 'repository.write' RepoModel().grant_user_group_permission(repo=HG_REPO, group_name=self.ug1, perm=new_perm_gr) # check perms u1_auth = AuthUser(user_id=self.u1.user_id) perms = { 'repositories_groups': {}, 'global': set([ 'hg.create.repository', 'repository.read', 'hg.register.manual_activate' ]), 'repositories': { HG_REPO: 'repository.read' } } assert u1_auth.permissions['repositories'][HG_REPO] == new_perm assert u1_auth.permissions['repositories_groups'] == perms[ 'repositories_groups']
def create_repo(self, name, **kwargs): if 'skip_if_exists' in kwargs: del kwargs['skip_if_exists'] r = Repository.get_by_repo_name(name) if r: return r if isinstance(kwargs.get('repo_group'), RepoGroup): kwargs['repo_group'] = kwargs['repo_group'].group_id form_data = self._get_repo_create_params(repo_name=name, **kwargs) cur_user = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN) RepoModel().create(form_data, cur_user) Session().commit() return Repository.get_by_repo_name(name)
def edit_perms(self, id): c.user_group = UserGroup.get_or_404(id) c.active = 'perms' repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.user_groups_array = repo_model.get_user_groups_js() defaults = {} # fill user group users for p in c.user_group.user_user_group_to_perm: defaults.update({'u_perm_%s' % p.user.username: p.permission.permission_name}) for p in c.user_group.user_group_user_group_to_perm: defaults.update({'g_perm_%s' % p.user_group.users_group_name: p.permission.permission_name}) return htmlfill.render( render('admin/user_groups/user_group_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False )
def test_remove_repo_detach_forks(self): repo = fixture.create_repo(name='test-repo-1') Session().commit() fork = fixture.create_fork(repo.repo_name, 'test-repo-fork-1') Session().commit() # fork of fork fixture.create_fork(fork.repo_name, 'test-repo-fork-fork-1') Session().commit() RepoModel().delete(repo=repo, forks='detach') Session().commit() try: assert Repository.get_by_repo_name(repo_name='test-repo-1') is None assert Repository.get_by_repo_name( repo_name='test-repo-fork-1') is not None assert Repository.get_by_repo_name( repo_name='test-repo-fork-fork-1') is not None finally: RepoModel().delete(repo='test-repo-fork-fork-1') RepoModel().delete(repo='test-repo-fork-1') Session().commit()
def __load_data(self, repo_name=None): """ Load defaults settings for edit, and update :param repo_name: """ c.repo_info = self._load_repo(repo_name) self.__load_defaults(c.repo_info) ##override defaults for exact repo info here git/hg etc choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info) c.landing_revs_choices = choices defaults = RepoModel()._get_defaults(repo_name) return defaults
def test_propagated_permission_from_users_group_by_explicit_perms_exist( self): # make group self.ug1 = fixture.create_user_group('G1') UserGroupModel().add_user_to_group(self.ug1, self.u1) # set user permission none RepoModel().grant_user_permission(repo=base.HG_REPO, user=self.u1, perm='repository.none') Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) assert u1_auth.permissions['repositories'][ base.HG_REPO] == 'repository.read' # inherit from default user # grant perm for group this should override permission from user RepoModel().grant_user_group_permission(repo=base.HG_REPO, group_name=self.ug1, perm='repository.write') # verify that user group permissions win u1_auth = AuthUser(user_id=self.u1.user_id) assert u1_auth.permissions['repositories'][ base.HG_REPO] == 'repository.write'
def test_inactive_user_group_does_not_affect_repo_permissions(self): self.ug1 = fixture.create_user_group('G1') user_group_model = UserGroupModel() user_group_model.add_user_to_group(self.ug1, self.u1) user_group_model.update(self.ug1, {'users_group_active': False}) # note: make u2 repo owner rather than u1, because the owner always has # admin permissions self.test_repo = fixture.create_repo(name='myownrepo', repo_type='hg', cur_user=self.u2) # enable admin access for user group on repo RepoModel().grant_user_group_permission(self.test_repo, group_name=self.ug1, perm='repository.admin') # enable only write access for default user on repo RepoModel().grant_user_permission(self.test_repo, user='******', perm='repository.write') Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) assert u1_auth.permissions['repositories'][ 'myownrepo'] == 'repository.write'
def test_propagated_permission_from_users_group_lower_weight(self): # make group self.ug1 = fixture.create_user_group('G1') # add user to group UserGroupModel().add_user_to_group(self.ug1, self.u1) # set permission to lower new_perm_h = 'repository.write' RepoModel().grant_user_permission(repo=base.HG_REPO, user=self.u1, perm=new_perm_h) Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) assert u1_auth.permissions['repositories'][base.HG_REPO] == new_perm_h # grant perm for group this should NOT override permission from user # since it's lower than granted new_perm_l = 'repository.read' RepoModel().grant_user_group_permission(repo=base.HG_REPO, group_name=self.ug1, perm=new_perm_l) # check perms u1_auth = AuthUser(user_id=self.u1.user_id) assert u1_auth.permissions['repositories'][base.HG_REPO] == new_perm_h
def index(self, format='html'): """GET /repos: All items in the collection""" # url('repos') _list = Repository.query()\ .order_by(func.lower(Repository.repo_name))\ .all() c.repos_list = RepoList(_list, perm_set=['repository.admin']) repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, admin=True, super_user_actions=True) #json used to render the grid c.data = json.dumps(repos_data) return render('admin/repos/repos.html')
def index(self): c.groups = self.scm_model.get_repo_groups() c.group = None c.repos_list = Repository.query()\ .filter(Repository.group_id == None)\ .order_by(func.lower(Repository.repo_name))\ .all() repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, admin=False) #json used to render the grid c.data = json.dumps(repos_data) return render('/index.html')
def test_zzz_fork_permission_page(self): usr = self.log_user(self.username, self.password)['user_id'] repo_name = self.REPO forks = Repository.query()\ .filter(Repository.repo_type == self.REPO_TYPE)\ .filter(Repository.fork_id != None).all() self.assertEqual(1, len(forks)) # set none RepoModel().grant_user_permission(repo=forks[0], user=usr, perm='repository.none') Session().commit() # fork shouldn't be there response = self.app.get(url(controller='forks', action='forks', repo_name=repo_name)) response.mustcontain('There are no forks yet')
def tearDown(self): if hasattr(self, 'test_repo'): RepoModel().delete(repo=self.test_repo) UserModel().delete(self.u1) UserModel().delete(self.u2) UserModel().delete(self.u3) UserModel().delete(self.a1) if hasattr(self, 'g1'): RepoGroupModel().delete(self.g1.group_id) if hasattr(self, 'g2'): RepoGroupModel().delete(self.g2.group_id) if hasattr(self, 'ug1'): UserGroupModel().delete(self.ug1, force=True) Session().commit()
def _set_perm_user(obj, user, perm): if isinstance(obj, RepoGroup): self.grant_user_permission(repo_group=obj, user=user, perm=perm) elif isinstance(obj, Repository): user = User.guess_instance(user) # private repos will not allow to change the default permissions # using recursive mode if obj.private and user.is_default_user: return # we set group permission but we have to switch to repo # permission perm = perm.replace('group.', 'repository.') RepoModel().grant_user_permission( repo=obj, user=user, perm=perm )
def test_owner_permissions_doesnot_get_overwritten_by_others(self): #create repo as USER, self.test_repo = fixture.create_repo(name='myownrepo', repo_type='hg', cur_user=self.u1) #he has permissions of admin as owner u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories']['myownrepo'], 'repository.admin') #set his permission as user, he should still be admin RepoModel().grant_user_permission(self.test_repo, user=self.u1, perm='repository.none') Session().commit() u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories']['myownrepo'], 'repository.admin')
def create_repo(self, name, repo_group=None, **kwargs): if 'skip_if_exists' in kwargs: del kwargs['skip_if_exists'] r = Repository.get_by_repo_name(name) if r: return r if isinstance(repo_group, RepoGroup): repo_group = repo_group.group_id form_data = self._get_repo_create_params(repo_name=name, **kwargs) form_data[ 'repo_group'] = repo_group # patch form dict so it can be used directly by model cur_user = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN) RepoModel().create(form_data, cur_user) Session().commit() ScmModel().mark_for_invalidation(name) return Repository.get_by_repo_name(name)
def __before__(self): super(PullrequestsController, self).__before__() repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.user_groups_array = repo_model.get_user_groups_js()
def repo2db_mapper(initial_repo_list, remove_obsolete=False, install_git_hooks=False, user=None, overwrite_git_hooks=False): """ maps all repos given in initial_repo_list, non existing repositories are created, if remove_obsolete is True it also check for db entries that are not in initial_repo_list and removes them. :param initial_repo_list: list of repositories found by scanning methods :param remove_obsolete: check for obsolete entries in database :param install_git_hooks: if this is True, also check and install git hook for a repo if missing :param overwrite_git_hooks: if this is True, overwrite any existing git hooks that may be encountered (even if user-deployed) """ from kallithea.model.repo import RepoModel from kallithea.model.scm import ScmModel sa = meta.Session() repo_model = RepoModel() if user is None: user = User.get_first_admin() added = [] ##creation defaults defs = Setting.get_default_repo_settings(strip_prefix=True) enable_statistics = defs.get('repo_enable_statistics') enable_locking = defs.get('repo_enable_locking') enable_downloads = defs.get('repo_enable_downloads') private = defs.get('repo_private') for name, repo in initial_repo_list.items(): group = map_groups(name) unicode_name = safe_unicode(name) db_repo = repo_model.get_by_repo_name(unicode_name) # found repo that is on filesystem not in Kallithea database if not db_repo: log.info('repository %s not found, creating now', name) added.append(name) desc = (repo.description if repo.description != 'unknown' else '%s repository' % name) new_repo = repo_model._create_repo( repo_name=name, repo_type=repo.alias, description=desc, repo_group=getattr(group, 'group_id', None), owner=user, enable_locking=enable_locking, enable_downloads=enable_downloads, enable_statistics=enable_statistics, private=private, state=Repository.STATE_CREATED ) sa.commit() # we added that repo just now, and make sure it has githook # installed, and updated server info if new_repo.repo_type == 'git': git_repo = new_repo.scm_instance ScmModel().install_git_hooks(git_repo) # update repository server-info log.debug('Running update server info') git_repo._update_server_info() new_repo.update_changeset_cache() elif install_git_hooks: if db_repo.repo_type == 'git': ScmModel().install_git_hooks(db_repo.scm_instance, force_create=overwrite_git_hooks) removed = [] # remove from database those repositories that are not in the filesystem unicode_initial_repo_list = set(safe_unicode(name) for name in initial_repo_list) for repo in sa.query(Repository).all(): if repo.repo_name not in unicode_initial_repo_list: if remove_obsolete: log.debug("Removing non-existing repository found in db `%s`", repo.repo_name) try: RepoModel(sa).delete(repo, forks='detach', fs_remove=False) sa.commit() except Exception: #don't hold further removals on error log.error(traceback.format_exc()) sa.rollback() removed.append(repo.repo_name) return added, removed
def create_repo(form_data, cur_user): from kallithea.model.repo import RepoModel from kallithea.model.user import UserModel from kallithea.model.db import Setting log = get_logger(create_repo) DBS = get_session() cur_user = UserModel(DBS)._get_user(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_locking = defs.get('repo_enable_locking') enable_downloads = defs.get('repo_enable_downloads') try: repo = RepoModel(DBS)._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_locking=enable_locking, enable_downloads=enable_downloads, state=state ) action_logger(cur_user, 'user_created_repo', form_data['repo_name_full'], '', DBS) DBS.commit() # now create this repo on Filesystem RepoModel(DBS)._create_filesystem_repo( repo_name=repo_name, repo_type=repo_type, repo_group=RepoModel(DBS)._get_repo_group(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(DBS)._delete_filesystem_repo(repo) raise # it's an odd fix to make celery fail task when exception occurs def on_failure(self, *args, **kwargs): pass return True
def create_update(self, old_pull_request, updaterev, title, description, reviewers_ids): org_repo = RepoModel()._get_repo(old_pull_request.org_repo.repo_name) org_ref_type, org_ref_name, org_rev = old_pull_request.org_ref.split(':') new_org_rev = self._get_ref_rev(org_repo, 'rev', updaterev) other_repo = RepoModel()._get_repo(old_pull_request.other_repo.repo_name) other_ref_type, other_ref_name, other_rev = old_pull_request.other_ref.split(':') # other_rev is ancestor #assert other_ref_type == 'branch', other_ref_type # TODO: what if not? new_other_rev = self._get_ref_rev(other_repo, other_ref_type, other_ref_name) cs_ranges, _cs_ranges_not, ancestor_rev = CompareController._get_changesets(org_repo.scm_instance.alias, other_repo.scm_instance, new_other_rev, # org and other "swapped" org_repo.scm_instance, new_org_rev) old_revisions = set(old_pull_request.revisions) revisions = [cs.raw_id for cs in cs_ranges] new_revisions = [r for r in revisions if r not in old_revisions] lost = old_revisions.difference(revisions) infos = ['This is an update of %s "%s".' % (h.canonical_url('pullrequest_show', repo_name=old_pull_request.other_repo.repo_name, pull_request_id=old_pull_request.pull_request_id), old_pull_request.title)] if lost: infos.append(_('Missing changesets since the previous pull request:')) for r in old_pull_request.revisions: if r in lost: rev_desc = org_repo.get_changeset(r).message.split('\n')[0] infos.append(' %s "%s"' % (h.short_id(r), rev_desc)) if new_revisions: infos.append(_('New changesets on %s %s since the previous pull request:') % (org_ref_type, org_ref_name)) for r in reversed(revisions): if r in new_revisions: rev_desc = org_repo.get_changeset(r).message.split('\n')[0] infos.append(' %s %s' % (h.short_id(r), h.shorter(rev_desc, 80))) if ancestor_rev == other_rev: infos.append(_("Ancestor didn't change - show diff since previous version:")) infos.append(h.canonical_url('compare_url', repo_name=org_repo.repo_name, # other_repo is always same as repo_name org_ref_type='rev', org_ref_name=h.short_id(org_rev), # use old org_rev as base other_ref_type='rev', other_ref_name=h.short_id(new_org_rev), )) # note: linear diff, merge or not doesn't matter else: infos.append(_('This pull request is based on another %s revision and there is no simple diff.') % other_ref_name) else: infos.append(_('No changes found on %s %s since previous version.') % (org_ref_type, org_ref_name)) # TODO: fail? # hack: ancestor_rev is not an other_ref but we want to show the # requested destination and have the exact ancestor new_other_ref = '%s:%s:%s' % (other_ref_type, other_ref_name, ancestor_rev) new_org_ref = '%s:%s:%s' % (org_ref_type, org_ref_name, new_org_rev) try: title, old_v = re.match(r'(.*)\(v(\d+)\)\s*$', title).groups() v = int(old_v) + 1 except (AttributeError, ValueError): v = 2 title = '%s (v%s)' % (title.strip(), v) # using a mail-like separator, insert new update info at the top of the list descriptions = description.replace('\r\n', '\n').split('\n-- \n', 1) description = descriptions[0].strip() + '\n\n-- \n' + '\n'.join(infos) if len(descriptions) > 1: description += '\n\n' + descriptions[1].strip() try: pull_request = PullRequestModel().create( self.authuser.user_id, old_pull_request.org_repo.repo_name, new_org_ref, old_pull_request.other_repo.repo_name, new_other_ref, revisions, reviewers_ids, title, description ) except UserInvalidException as u: h.flash(_('Invalid reviewer "%s" specified') % u, category='error') raise HTTPBadRequest() except Exception: h.flash(_('Error occurred while creating pull request'), category='error') log.error(traceback.format_exc()) raise HTTPFound(location=old_pull_request.url()) ChangesetCommentsModel().create( text=_('Closed, replaced by %s .') % pull_request.url(canonical=True), repo=old_pull_request.other_repo.repo_id, user=c.authuser.user_id, pull_request=old_pull_request.pull_request_id, closing_pr=True) PullRequestModel().close_pull_request(old_pull_request.pull_request_id) Session().commit() h.flash(_('Pull request update created'), category='success') raise HTTPFound(location=pull_request.url())
def show(self, repo_name, pull_request_id, extra=None): repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.user_groups_array = repo_model.get_user_groups_js() c.pull_request = PullRequest.get_or_404(pull_request_id) c.allowed_to_change_status = self._get_is_allowed_change_status(c.pull_request) cc_model = ChangesetCommentsModel() cs_model = ChangesetStatusModel() # pull_requests repo_name we opened it against # ie. other_repo must match if repo_name != c.pull_request.other_repo.repo_name: raise HTTPNotFound # load compare data into template context c.cs_repo = c.pull_request.org_repo (c.cs_ref_type, c.cs_ref_name, c.cs_rev) = c.pull_request.org_ref.split(':') c.a_repo = c.pull_request.other_repo (c.a_ref_type, c.a_ref_name, c.a_rev) = c.pull_request.other_ref.split(':') # other_rev is ancestor org_scm_instance = c.cs_repo.scm_instance # property with expensive cache invalidation check!!! c.cs_repo = c.cs_repo try: c.cs_ranges = [org_scm_instance.get_changeset(x) for x in c.pull_request.revisions] except ChangesetDoesNotExistError: c.cs_ranges = [] c.cs_ranges_org = None # not stored and not important and moving target - could be calculated ... revs = [ctx.revision for ctx in reversed(c.cs_ranges)] c.jsdata = json.dumps(graph_data(org_scm_instance, revs)) c.is_range = False if c.a_ref_type == 'rev': # this looks like a free range where target is ancestor cs_a = org_scm_instance.get_changeset(c.a_rev) root_parents = c.cs_ranges[0].parents c.is_range = cs_a in root_parents #c.merge_root = len(root_parents) > 1 # a range starting with a merge might deserve a warning avail_revs = set() avail_show = [] c.cs_branch_name = c.cs_ref_name other_scm_instance = c.a_repo.scm_instance c.update_msg = "" c.update_msg_other = "" try: if org_scm_instance.alias == 'hg' and c.a_ref_name != 'ancestor': if c.cs_ref_type != 'branch': c.cs_branch_name = org_scm_instance.get_changeset(c.cs_ref_name).branch # use ref_type ? c.a_branch_name = c.a_ref_name if c.a_ref_type != 'branch': try: c.a_branch_name = other_scm_instance.get_changeset(c.a_ref_name).branch # use ref_type ? except EmptyRepositoryError: c.a_branch_name = 'null' # not a branch name ... but close enough # candidates: descendants of old head that are on the right branch # and not are the old head itself ... # and nothing at all if old head is a descendant of target ref name if not c.is_range and other_scm_instance._repo.revs('present(%s)::&%s', c.cs_ranges[-1].raw_id, c.a_branch_name): c.update_msg = _('This pull request has already been merged to %s.') % c.a_branch_name elif c.pull_request.is_closed(): c.update_msg = _('This pull request has been closed and can not be updated.') else: # look for descendants of PR head on source branch in org repo avail_revs = org_scm_instance._repo.revs('%s:: & branch(%s)', revs[0], c.cs_branch_name) if len(avail_revs) > 1: # more than just revs[0] # also show changesets that not are descendants but would be merged in targethead = other_scm_instance.get_changeset(c.a_branch_name).raw_id if org_scm_instance.path != other_scm_instance.path: # Note: org_scm_instance.path must come first so all # valid revision numbers are 100% org_scm compatible # - both for avail_revs and for revset results hgrepo = unionrepo.unionrepository(org_scm_instance.baseui, org_scm_instance.path, other_scm_instance.path) else: hgrepo = org_scm_instance._repo show = set(hgrepo.revs('::%ld & !::parents(%s) & !::%s', avail_revs, revs[0], targethead)) c.update_msg = _('The following changes are available on %s:') % c.cs_branch_name else: show = set() avail_revs = set() # drop revs[0] c.update_msg = _('No changesets found for updating this pull request.') # TODO: handle branch heads that not are tip-most brevs = org_scm_instance._repo.revs('%s - %ld - %s', c.cs_branch_name, avail_revs, revs[0]) if brevs: # also show changesets that are on branch but neither ancestors nor descendants show.update(org_scm_instance._repo.revs('::%ld - ::%ld - ::%s', brevs, avail_revs, c.a_branch_name)) show.add(revs[0]) # make sure graph shows this so we can see how they relate c.update_msg_other = _('Note: Branch %s has another head: %s.') % (c.cs_branch_name, h.short_id(org_scm_instance.get_changeset((max(brevs))).raw_id)) avail_show = sorted(show, reverse=True) elif org_scm_instance.alias == 'git': c.cs_repo.scm_instance.get_changeset(c.cs_rev) # check it exists - raise ChangesetDoesNotExistError if not c.update_msg = _("Git pull requests don't support updates yet.") except ChangesetDoesNotExistError: c.update_msg = _('Error: revision %s was not found. Please create a new pull request!') % c.cs_rev c.avail_revs = avail_revs c.avail_cs = [org_scm_instance.get_changeset(r) for r in avail_show] c.avail_jsdata = json.dumps(graph_data(org_scm_instance, avail_show)) raw_ids = [x.raw_id for x in c.cs_ranges] c.cs_comments = c.cs_repo.get_comments(raw_ids) c.statuses = c.cs_repo.statuses(raw_ids) ignore_whitespace = request.GET.get('ignorews') == '1' line_context = request.GET.get('context', 3) c.ignorews_url = _ignorews_url c.context_url = _context_url c.fulldiff = request.GET.get('fulldiff') diff_limit = self.cut_off_limit if not c.fulldiff else None # we swap org/other ref since we run a simple diff on one repo log.debug('running diff between %s and %s in %s', c.a_rev, c.cs_rev, org_scm_instance.path) try: txtdiff = org_scm_instance.get_diff(rev1=safe_str(c.a_rev), rev2=safe_str(c.cs_rev), ignore_whitespace=ignore_whitespace, context=line_context) except ChangesetDoesNotExistError: txtdiff = _("The diff can't be shown - the PR revisions could not be found.") diff_processor = diffs.DiffProcessor(txtdiff or '', format='gitdiff', diff_limit=diff_limit) _parsed = diff_processor.prepare() c.limited_diff = False if isinstance(_parsed, LimitedDiffContainer): c.limited_diff = True c.files = [] c.changes = {} c.lines_added = 0 c.lines_deleted = 0 for f in _parsed: st = f['stats'] c.lines_added += st['added'] c.lines_deleted += st['deleted'] fid = h.FID('', f['filename']) c.files.append([fid, f['operation'], f['filename'], f['stats']]) htmldiff = diff_processor.as_html(enable_comments=True, parsed_lines=[f]) c.changes[fid] = [f['operation'], f['filename'], htmldiff] # inline comments c.inline_cnt = 0 c.inline_comments = cc_model.get_inline_comments( c.db_repo.repo_id, pull_request=pull_request_id) # count inline comments for __, lines in c.inline_comments: for comments in lines.values(): c.inline_cnt += len(comments) # comments c.comments = cc_model.get_comments(c.db_repo.repo_id, pull_request=pull_request_id) # (badly named) pull-request status calculation based on reviewer votes (c.pull_request_reviewers, c.pull_request_pending_reviewers, c.current_voting_result, ) = cs_model.calculate_pull_request_result(c.pull_request) c.changeset_statuses = ChangesetStatus.STATUSES c.as_form = False c.ancestor = None # there is one - but right here we don't know which return render('/pullrequests/pullrequest_show.html')
def __load_data(self): repo_model = RepoModel() c.users_array = repo_model.get_users_js() c.user_groups_array = repo_model.get_user_groups_js()
def update_repo_info(self): RepoModel.update_repoinfo()