def __rename_group(self, old, old_parent_id, new, new_parent_id): """ Renames a group on filesystem :param group_name: """ log.debug('renaming repos group from %s to %s', old, new) if new_parent_id: paths = Group.get(new_parent_id).full_path.split(Group.url_sep()) new_parent_path = os.sep.join(paths) else: new_parent_path = '' if old_parent_id: paths = Group.get(old_parent_id).full_path.split(Group.url_sep()) old_parent_path = os.sep.join(paths) else: old_parent_path = '' old_path = os.path.join(self.repos_path, old_parent_path, old) new_path = os.path.join(self.repos_path, new_parent_path, new) log.debug('renaming repos paths from %s to %s', old_path, new_path) if os.path.isdir(new_path): raise Exception('Was trying to rename to already ' 'existing dir %s' % new_path) shutil.move(old_path, new_path)
def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False): """ makes repository on filesystem. It's group aware means it'll create a repository within a group, and alter the paths accordingly of group location :param repo_name: :param alias: :param parent_id: :param clone_uri: """ from rhodecode.lib.utils import check_repo if new_parent_id: paths = Group.get(new_parent_id).full_path.split(Group.url_sep()) new_parent_path = os.sep.join(paths) else: new_parent_path = "" repo_path = os.path.join(*map(lambda x: safe_str(x), [self.repos_path, new_parent_path, repo_name])) if check_repo(repo_path, self.repos_path): log.info("creating repo %s in %s @ %s", repo_name, repo_path, clone_uri) backend = get_backend(alias) backend(repo_path, create=True, src_url=clone_uri)
def update(self, repos_group_id, form_data): try: repos_group = Group.get(repos_group_id) old_path = repos_group.full_path #change properties repos_group.group_description = form_data['group_description'] repos_group.parent_group = Group.get(form_data['group_parent_id']) repos_group.group_name = repos_group.get_new_name(form_data['group_name']) new_path = repos_group.full_path self.sa.add(repos_group) self.__rename_group(old_path, new_path) # we need to get all repositories from this new group and # rename them accordingly to new group path for r in repos_group.repositories: r.repo_name = r.get_new_name(r.just_name) self.sa.add(r) self.sa.commit() return repos_group except: log.error(traceback.format_exc()) self.sa.rollback() raise
def validate_python(self, value, state): #TODO WRITE VALIDATIONS group_name = value.get('group_name') group_parent_id = int(value.get('group_parent_id') or -1) # slugify repo group just in case :) slug = repo_name_slug(group_name) # check for parent of self if edit and old_data['group_id'] == group_parent_id: e_dict = {'group_parent_id':_('Cannot assign this group ' 'as parent')} raise formencode.Invalid('', value, state, error_dict=e_dict) old_gname = None if edit: old_gname = Group.get( old_data.get('group_id')).group_name if old_gname != group_name or not edit: # check filesystem gr = Group.query().filter(Group.group_name == slug)\ .filter(Group.group_parent_id == group_parent_id).scalar() if gr: e_dict = {'group_name':_('This group already exists')} raise formencode.Invalid('', value, state, error_dict=e_dict)
def test_remove_group(self): sg1 = self.__make_group('deleteme') self.__delete_group(sg1.group_id) self.assertEqual(Group.get(sg1.group_id), None) self.assertFalse(self.__check_path('deteteme')) sg1 = self.__make_group('deleteme', parent_id=self.g1.group_id) self.__delete_group(sg1.group_id) self.assertEqual(Group.get(sg1.group_id), None) self.assertFalse(self.__check_path('test1', 'deteteme'))
def validate_python(self, value, state): # TODO WRITE VALIDATIONS group_name = value.get('group_name') group_parent_id = value.get('group_parent_id') # slugify repo group just in case :) slug = repo_name_slug(group_name) # check for parent of self parent_of_self = lambda: ( old_data['group_id'] == int(group_parent_id) if group_parent_id else False ) if edit and parent_of_self(): e_dict = { 'group_parent_id': _('Cannot assign this group as parent') } raise formencode.Invalid('', value, state, error_dict=e_dict) old_gname = None if edit: old_gname = Group.get( old_data.get('group_id')).group_name if old_gname != group_name or not edit: # check group gr = Group.query()\ .filter(Group.group_name == slug)\ .filter(Group.group_parent_id == group_parent_id)\ .scalar() if gr: e_dict = { 'group_name': _('This group already exists') } raise formencode.Invalid('', value, state, error_dict=e_dict) # check for same repo repo = Repository.query()\ .filter(Repository.repo_name == slug)\ .scalar() if repo: e_dict = { 'group_name': _('Repository with this name already exists') } raise formencode.Invalid('', value, state, error_dict=e_dict)
def to_python(self, value, state): repo_name = value.get('repo_name') slug = repo_name_slug(repo_name) if slug in [ADMIN_PREFIX, '']: e_dict = {'repo_name': _('This repository name is disallowed')} raise formencode.Invalid('', value, state, error_dict=e_dict) if value.get('repo_group'): gr = Group.get(value.get('repo_group')) group_path = gr.full_path # value needs to be aware of group name in order to check # db key This is an actual just the name to store in the # database repo_name_full = group_path + Group.url_sep() + repo_name else: group_path = '' repo_name_full = repo_name value['repo_name_full'] = repo_name_full rename = old_data.get('repo_name') != repo_name_full create = not edit if rename or create: if group_path != '': if RepoModel().get_by_repo_name(repo_name_full,): e_dict = {'repo_name':_('This repository already ' 'exists in a group "%s"') % gr.group_name} raise formencode.Invalid('', value, state, error_dict=e_dict) elif Group.get_by_group_name(repo_name_full): e_dict = {'repo_name':_('There is a group with this' ' name already "%s"') % repo_name_full} raise formencode.Invalid('', value, state, error_dict=e_dict) elif RepoModel().get_by_repo_name(repo_name_full): e_dict = {'repo_name':_('This repository ' 'already exists')} raise formencode.Invalid('', value, state, error_dict=e_dict) return value
def index(self, format='html'): """GET /repos_groups: All items in the collection""" # url('repos_groups') sk = lambda g:g.parents[0].group_name if g.parents else g.group_name c.groups = sorted(Group.query().all(), key=sk) return render('admin/repos_groups/repos_groups_show.html')
def update(self, repos_group_id, form_data): try: repos_group = Group.get(repos_group_id) old_name = repos_group.group_name old_parent_id = repos_group.group_parent_id repos_group.group_name = form_data['group_name'] repos_group.group_description = \ form_data['group_description'] repos_group.group_parent_id = form_data['group_parent_id'] self.sa.add(repos_group) if old_name != form_data['group_name'] or (old_parent_id != form_data['group_parent_id']): self.__rename_group(old=old_name, old_parent_id=old_parent_id, new=form_data['group_name'], new_parent_id=form_data['group_parent_id']) self.sa.commit() except: log.error(traceback.format_exc()) self.sa.rollback() raise
def index(self): c.repos_list = self.scm_model.get_repos() c.groups = Group.query().filter(Group.group_parent_id == None).all() return render('/index.html')
def delete(self, id): """DELETE /repos_groups/id: 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('repos_group', id=ID), # method='delete') # url('repos_group', id=ID) repos_group_model = ReposGroupModel() gr = Group.get(id) repos = gr.repositories.all() if repos: h.flash(_('This group contains %s repositores and cannot be ' 'deleted' % len(repos)), category='error') return redirect(url('repos_groups')) try: repos_group_model.delete(id) h.flash(_('removed repos group %s' % gr.group_name), category='success') #TODO: in future action_logger(, '', '', '', self.sa) except IntegrityError, e: if e.message.find('groups_group_parent_id_fkey'): log.error(traceback.format_exc()) h.flash(_('Cannot delete this group it still contains ' 'subgroups'), category='warning') else: log.error(traceback.format_exc()) h.flash(_('error occurred during deletion of repos ' 'group %s' % gr.group_name), category='error')
def __load_defaults(self): c.repo_groups = Group.groups_choices() 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.users_groups_array = repo_model.get_users_groups_js()
def update(self, id): """PUT /repos_groups/id: 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('repos_group', id=ID), # method='put') # url('repos_group', id=ID) self.__load_defaults() c.repos_group = Group.get(id) repos_group_model = ReposGroupModel() repos_group_form = ReposGroupForm(edit=True, old_data=c.repos_group.get_dict(), available_groups= c.repo_groups_choices)() try: form_result = repos_group_form.to_python(dict(request.POST)) repos_group_model.update(id, form_result) h.flash(_('updated repos group %s') \ % form_result['group_name'], category='success') #TODO: in futureaction_logger(, '', '', '', self.sa) except formencode.Invalid, errors: return htmlfill.render( render('admin/repos_groups/repos_groups_edit.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
def create(self, form_data): try: new_repos_group = Group() new_repos_group.group_name = form_data['group_name'] new_repos_group.group_description = \ form_data['group_description'] new_repos_group.group_parent_id = form_data['group_parent_id'] self.sa.add(new_repos_group) self.__create_group(form_data['group_name'], form_data['group_parent_id']) self.sa.commit() except: log.error(traceback.format_exc()) self.sa.rollback() raise
def test_update_group_parent(self): sg1 = self.__make_group('initial', parent_id=self.g1.group_id) new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g1.group_id) self.assertTrue(self.__check_path('test1', 'after')) self.assertEqual(Group.get_by_group_name('test1/initial'), None) new_sg1 = self.__update_group(sg1.group_id, 'after', parent_id=self.g3.group_id) self.assertTrue(self.__check_path('test3', 'after')) self.assertEqual(Group.get_by_group_name('test3/initial'), None) new_sg1 = self.__update_group(sg1.group_id, 'hello') self.assertTrue(self.__check_path('hello')) self.assertEqual(Group.get_by_group_name('hello'), new_sg1)
def create_repository(self): """GET /_admin/create_repository: Form to create a new item""" c.repo_groups = Group.groups_choices() c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) new_repo = request.GET.get('repo', '') c.new_repo = repo_name_slug(new_repo) return render('admin/repos/repo_add_create_repository.html')
def delete(self, users_group_id): try: users_group = Group.get(users_group_id) self.sa.delete(users_group) self.__delete_group(users_group) self.sa.commit() except: log.error(traceback.format_exc()) self.sa.rollback() raise
def __delete_group(self, group): """ Deletes a group from a filesystem :param group: instance of group from database """ paths = group.full_path.split(Group.url_sep()) paths = os.sep.join(paths) rm_path = os.path.join(self.repos_path, paths) os.rmdir(rm_path)
def __make_group(self, path, desc='desc', parent_id=None, skip_if_exists=False): gr = Group.get_by_group_name(path) if gr and skip_if_exists: return gr form_data = dict(group_name=path, group_description=desc, group_parent_id=parent_id) gr = ReposGroupModel().create(form_data) return gr
def __create_group(self, group_name, parent_id): """ makes repositories group on filesystem :param repo_name: :param parent_id: """ if parent_id: paths = Group.get(parent_id).full_path.split(Group.url_sep()) parent_path = os.sep.join(paths) else: parent_path = '' create_path = os.path.join(self.repos_path, parent_path, group_name) log.debug('creating new group in %s', create_path) if os.path.isdir(create_path): raise Exception('That directory already exists !') os.makedirs(create_path)
def __load_data(self, group_id): """ Load defaults settings for edit, and update :param group_id: """ self.__load_defaults() repo_group = Group.get(group_id) data = repo_group.get_dict() return data
def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False): """ makes repository on filesystem. It's group aware means it'll create a repository within a group, and alter the paths accordingly of group location :param repo_name: :param alias: :param parent_id: :param clone_uri: """ from rhodecode.lib.utils import is_valid_repo,is_valid_repos_group if new_parent_id: paths = Group.get(new_parent_id).full_path.split(Group.url_sep()) new_parent_path = os.sep.join(paths) else: new_parent_path = '' repo_path = os.path.join(*map(lambda x:safe_str(x), [self.repos_path, new_parent_path, repo_name])) # check if this path is not a repository if is_valid_repo(repo_path, self.repos_path): raise Exception('This path %s is a valid repository' % repo_path) # check if this path is a group if is_valid_repos_group(repo_path, self.repos_path): raise Exception('This path %s is a valid group' % repo_path) log.info('creating repo %s in %s @ %s', repo_name, repo_path, clone_uri) backend = get_backend(alias) backend(repo_path, create=True, src_url=clone_uri)
def edit(self, id, format='html'): """GET /repos_groups/id/edit: Form to edit an existing item""" # url('edit_repos_group', id=ID) id_ = int(id) c.repos_group = Group.get(id_) defaults = self.__load_data(id_) # we need to exclude this group from the group list for editing c.repo_groups = filter(lambda x:x[0] != id_, c.repo_groups) return htmlfill.render( render('admin/repos_groups/repos_groups_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False )
def create_repo(self, apiuser, name, owner_name, description='', repo_type='hg', private=False): """ Create a repository :param apiuser :param name :param description :param type :param private :param owner_name """ try: try: owner = User.get_by_username(owner_name) except NoResultFound: raise JSONRPCError('unknown user %s' % owner) if self.get_repo(apiuser, name): raise JSONRPCError("repo %s already exist" % name) groups = name.split('/') real_name = groups[-1] groups = groups[:-1] parent_id = None for g in groups: group = Group.get_by_group_name(g) if not group: group = ReposGroupModel().create(dict(group_name=g, group_description='', group_parent_id=parent_id)) parent_id = group.group_id RepoModel().create(dict(repo_name=real_name, repo_name_full=name, description=description, private=private, repo_type=repo_type, repo_group=parent_id, clone_uri=None), owner) except Exception: log.error(traceback.format_exc()) raise JSONRPCError('failed to create repository %s' % name)
def repo2db_mapper(initial_repo_list, remove_obsolete=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 """ sa = meta.Session() rm = RepoModel() user = sa.query(User).filter(User.admin == True).first() added = [] # fixup groups paths to new format on the fly # TODO: remove this in future for g in Group.query().all(): g.group_name = g.get_new_name(g.name) sa.add(g) for name, repo in initial_repo_list.items(): group = map_groups(name.split(Repository.url_sep())) if not rm.get_by_repo_name(name, cache=False): log.info("repository %s not found creating default", name) added.append(name) form_data = { "repo_name": name, "repo_name_full": name, "repo_type": repo.alias, "description": repo.description if repo.description != "unknown" else "%s repository" % name, "private": False, "group_id": getattr(group, "group_id", None), } rm.create(form_data, user, just_db=True) removed = [] if remove_obsolete: # remove from database those repositories that are not in the filesystem for repo in sa.query(Repository).all(): if repo.repo_name not in initial_repo_list.keys(): removed.append(repo.repo_name) sa.delete(repo) sa.commit() return added, removed
def index(self): sortables = ['name', 'description', 'last_change', 'tip', 'owner'] current_sort = request.GET.get('sort', 'name') current_sort_slug = current_sort.replace('-', '') if current_sort_slug not in sortables: c.sort_by = 'name' current_sort_slug = c.sort_by else: c.sort_by = current_sort c.sort_slug = current_sort_slug sort_key = current_sort_slug + '_sort' c.repos_list = self.scm_model.get_repos(sort_key=sort_key) c.groups = Group.query().filter(Group.group_parent_id == None).all() return render('/index.html')
def show(self, id, format='html'): """GET /repos_groups/id: Show a specific item""" # url('repos_group', id=ID) c.group = Group.get(id) if c.group: c.group_repos = c.group.repositories.all() else: return redirect(url('home')) #overwrite our cached list with current filter gr_filter = c.group_repos c.cached_repo_list = self.scm_model.get_repos(all_repos=gr_filter) c.repos_list = c.cached_repo_list c.repo_cnt = 0 c.groups = self.sa.query(Group).order_by(Group.group_name)\ .filter(Group.group_parent_id == id).all() return render('admin/repos_groups/repos_groups.html')
def show(self, id, format='html'): """GET /repos_groups/id: Show a specific item""" # url('repos_group', id=ID) gr = c.group = Group.get(id) if c.group: c.group_repos = c.group.repositories.all() else: return redirect(url('home')) sortables = ['name', 'description', 'last_change', 'tip', 'owner'] current_sort = request.GET.get('sort', 'name') current_sort_slug = current_sort.replace('-', '') if current_sort_slug not in sortables: c.sort_by = 'name' current_sort_slug = c.sort_by else: c.sort_by = current_sort c.sort_slug = current_sort_slug sort_key = current_sort_slug + '_sort' #overwrite our cached list with current filter gr_filter = c.group_repos c.cached_repo_list = self.scm_model.get_repos(all_repos=gr_filter) c.repos_list = c.cached_repo_list c.repo_cnt = 0 c.groups = self.sa.query(Group).order_by(Group.group_name)\ .filter(Group.group_parent_id == id).all() return render('admin/repos_groups/repos_groups.html')
def test_rename_single_group(self): sg1 = self.__make_group('initial') new_sg1 = self.__update_group(sg1.group_id, 'after') self.assertTrue(self.__check_path('after')) self.assertEqual(Group.get_by_group_name('initial'), None)
def __load_defaults(self): c.repo_groups = Group.groups_choices() c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)