def create(self): self.__load_defaults() # permissions for can create group based on parent_id are checked # here in the Form repo_group_form = RepoGroupForm(repo_groups=c.repo_groups) try: form_result = repo_group_form.to_python(dict(request.POST)) gr = RepoGroupModel().create( group_name=form_result['group_name'], group_description=form_result['group_description'], parent=form_result['parent_group_id'], owner=request.authuser.user_id, # TODO: make editable copy_permissions=form_result['group_copy_permissions'] ) Session().commit() #TODO: in future action_logger(, '', '', '') except formencode.Invalid as errors: return htmlfill.render( render('admin/repo_groups/repo_group_add.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 creation of repository group %s') \ % request.POST.get('group_name'), category='error') parent_group_id = form_result['parent_group_id'] #TODO: maybe we should get back to the main view, not the admin one raise HTTPFound(location=url('repos_groups', parent_group=parent_group_id)) h.flash(_('Created repository group %s') % gr.group_name, category='success') raise HTTPFound(location=url('repos_group_home', group_name=gr.group_name))
def create(self): users_group_form = UserGroupForm()() try: form_result = users_group_form.to_python(dict(request.POST)) ug = UserGroupModel().create(name=form_result['users_group_name'], description=form_result['user_group_description'], owner=request.authuser.user_id, active=form_result['users_group_active']) gr = form_result['users_group_name'] action_logger(request.authuser, 'admin_created_users_group:%s' % gr, None, request.ip_addr) h.flash(h.literal(_('Created user group %s') % h.link_to(h.escape(gr), url('edit_users_group', id=ug.users_group_id))), category='success') Session().commit() except formencode.Invalid as errors: return htmlfill.render( render('admin/user_groups/user_group_add.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 creation of user group %s') \ % request.POST.get('users_group_name'), category='error') raise HTTPFound(location=url('users_groups'))
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_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_ip(self, id): ip_id = request.POST.get('del_ip_id') user_model = UserModel() user_model.delete_extra_ip(id, ip_id) Session().commit() h.flash(_("Removed IP address from user whitelist"), category='success') if 'default_user' in request.POST: raise HTTPFound(location=url('admin_permissions_ips')) raise HTTPFound(location=url('edit_user_ips', id=id))
def link_to_ref(repo_name, ref_type, ref_name, rev=None): """ Return full markup for a href to changeset_home for a changeset. If ref_type is branch it will link to changelog. ref_name is shortened if ref_type is 'rev'. if rev is specified show it too, explicitly linking to that revision. """ txt = short_ref(ref_type, ref_name) if ref_type == 'branch': u = url('changelog_home', repo_name=repo_name, branch=ref_name) else: u = url('changeset_home', repo_name=repo_name, revision=ref_name) l = link_to(repo_name + '#' + txt, u) if rev and ref_type != 'rev': l = literal('%s (%s)' % (l, link_to(short_id(rev), url('changeset_home', repo_name=repo_name, revision=rev)))) return l
def edit_statistics(self, repo_name): c.repo_info = self._load_repo() repo = c.repo_info.scm_instance if c.repo_info.stats: # this is on what revision we ended up so we add +1 for count last_rev = c.repo_info.stats.stat_on_revision + 1 else: last_rev = 0 c.stats_revision = last_rev c.repo_last_rev = repo.count() if repo.revisions else 0 if last_rev == 0 or c.repo_last_rev == 0: c.stats_percentage = 0 else: c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100) c.active = 'statistics' if request.POST: try: RepoModel().delete_stats(repo_name) Session().commit() except Exception as e: log.error(traceback.format_exc()) h.flash(_('An error occurred during deletion of repository stats'), category='error') raise HTTPFound(location=url('edit_repo_statistics', repo_name=c.repo_name)) return render('admin/repos/repo_edit.html')
def update(self, id): _form = DefaultsForm()() try: form_result = _form.to_python(dict(request.POST)) for k, v in form_result.iteritems(): setting = Setting.create_or_update(k, v) Session().commit() h.flash(_('Default settings updated successfully'), category='success') except formencode.Invalid as errors: defaults = errors.value return htmlfill.render( render('admin/defaults/defaults.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 defaults'), category='error') raise HTTPFound(location=url('defaults'))
def create(self): self.__load_defaults() form_result = {} try: # CanWriteGroup validators checks permissions of this POST form_result = RepoForm(repo_groups=c.repo_groups, landing_revs=c.landing_revs_choices)() \ .to_python(dict(request.POST)) # create is done sometimes async on celery, db transaction # management is handled there. task = RepoModel().create(form_result, request.authuser.user_id) task_id = task.task_id except formencode.Invalid as errors: log.info(errors) return htmlfill.render( render('admin/repos/repo_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, force_defaults=False, encoding="UTF-8") except Exception: log.error(traceback.format_exc()) msg = (_('Error creating repository %s') % form_result.get('repo_name')) h.flash(msg, category='error') raise HTTPFound(location=url('home')) raise HTTPFound(location=h.url('repo_creating_home', repo_name=form_result['repo_name_full'], task_id=task_id))
def edit_advanced(self, repo_name): c.repo_info = self._load_repo() c.default_user_id = User.get_default_user().user_id c.in_public_journal = UserFollowing.query() \ .filter(UserFollowing.user_id == c.default_user_id) \ .filter(UserFollowing.follows_repository == c.repo_info).scalar() _repos = Repository.query(sorted=True).all() read_access_repos = RepoList(_repos, perm_level='read') c.repos_list = [(None, _('-- Not a fork --'))] c.repos_list += [(x.repo_id, x.repo_name) for x in read_access_repos if x.repo_id != c.repo_info.repo_id] defaults = { 'id_fork_of': c.repo_info.fork_id if c.repo_info.fork_id else '' } c.active = 'advanced' if request.POST: raise HTTPFound(location=url('repo_edit_advanced')) return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def create(self): c.default_extern_type = User.DEFAULT_AUTH_TYPE c.default_extern_name = '' user_model = UserModel() user_form = UserForm()() try: form_result = user_form.to_python(dict(request.POST)) user = user_model.create(form_result) action_logger(request.authuser, 'admin_created_user:%s' % user.username, None, request.ip_addr) h.flash(_('Created user %s') % user.username, category='success') Session().commit() except formencode.Invalid as errors: return htmlfill.render( render('admin/users/user_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except UserCreationError as e: h.flash(e, 'error') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during creation of user %s') \ % request.POST.get('username'), category='error') raise HTTPFound(location=url('edit_user', id=user.user_id))
def lnk(rev, repo_name): lazy_cs = False title_ = None url_ = '#' if isinstance(rev, BaseChangeset) or isinstance(rev, AttributeDict): if rev.op and rev.ref_name: if rev.op == 'delete_branch': lbl = _('Deleted branch: %s') % rev.ref_name elif rev.op == 'tag': lbl = _('Created tag: %s') % rev.ref_name else: lbl = 'Unknown operation %s' % rev.op else: lazy_cs = True lbl = rev.short_id[:8] url_ = url('changeset_home', repo_name=repo_name, revision=rev.raw_id) else: # changeset cannot be found - it might have been stripped or removed lbl = rev[:12] title_ = _('Changeset %s not found') % lbl if parse_cs: return link_to(lbl, url_, title=title_, **{'data-toggle': 'tooltip'}) return link_to(lbl, url_, class_='lazy-cs' if lazy_cs else '', **{'data-raw_id':rev.raw_id, 'data-repo_name':repo_name})
def _replace(match_obj): url = match_obj.group('url') if url is not None: return '<a href="%(url)s">%(url)s</a>' % {'url': url} mention = match_obj.group('mention') if mention is not None: return '<b>%s</b>' % mention hash_ = match_obj.group('hash') if hash_ is not None and repo_name is not None: from kallithea.config.routing import url # doh, we need to re-import url to mock it later return '<a class="revision-link" href="%(url)s">%(hash)s</a>' % { 'url': url('changeset_home', repo_name=repo_name, revision=hash_), 'hash': hash_, } bold = match_obj.group('bold') if bold is not None: return '<b>*%s*</b>' % _urlify(bold[1:-1]) if stylize: seen = match_obj.group('seen') if seen: return '<div class="metatag" data-tag="see">see => %s</div>' % seen license = match_obj.group('license') if license: return '<div class="metatag" data-tag="license"><a href="http:\/\/www.opensource.org/licenses/%s">%s</a></div>' % (license, license) tagtype = match_obj.group('tagtype') if tagtype: tagvalue = match_obj.group('tagvalue') return '<div class="metatag" data-tag="%s">%s => <a href="/%s">%s</a></div>' % (tagtype, tagtype, tagvalue, tagvalue) lang = match_obj.group('lang') if lang: return '<div class="metatag" data-tag="lang">%s</div>' % lang tag = match_obj.group('tag') if tag: return '<div class="metatag" data-tag="%s">%s</div>' % (tag, tag) return match_obj.group(0)
def my_account_api_keys_add(self): lifetime = safe_int(request.POST.get('lifetime'), -1) description = request.POST.get('description') ApiKeyModel().create(request.authuser.user_id, description, lifetime) Session().commit() h.flash(_("API key successfully created"), category='success') raise HTTPFound(location=url('my_account_api_keys'))
def my_account_emails_delete(self): email_id = request.POST.get('del_email_id') user_model = UserModel() user_model.delete_extra_email(request.authuser.user_id, email_id) Session().commit() h.flash(_("Removed email from user"), category='success') raise HTTPFound(location=url('my_account_emails'))
def __get_cs(self, rev, silent_empty=False): """ Safe way to get changeset if error occur it redirects to tip with proper message :param rev: revision to fetch :silent_empty: return None if repository is empty """ try: return c.db_repo_scm_instance.get_changeset(rev) except EmptyRepositoryError as e: if silent_empty: return None url_ = url('files_add_home', repo_name=c.repo_name, revision=0, f_path='', anchor='edit') add_new = h.link_to(_('Click here to add new file'), url_, class_="alert-link") h.flash(h.literal(_('There are no files yet. %s') % add_new), category='warning') raise HTTPNotFound() except (ChangesetDoesNotExistError, LookupError): msg = _('Such revision does not exist for this repository') h.flash(msg, category='error') raise HTTPNotFound() except RepositoryError as e: h.flash(safe_str(e), category='error') raise HTTPNotFound()
def _load_repo(self): repo_obj = c.db_repo if repo_obj is None: h.not_mapped_error(c.repo_name) raise HTTPFound(location=url('repos')) return repo_obj
def delete_email(self, id): user = self._get_user_or_raise_if_default(id) email_id = request.POST.get('del_email_id') user_model = UserModel() user_model.delete_extra_email(id, email_id) Session().commit() h.flash(_("Removed email from user"), category='success') raise HTTPFound(location=url('edit_user_emails', id=id))
def add_api_key(self, id): c.user = self._get_user_or_raise_if_default(id) lifetime = safe_int(request.POST.get('lifetime'), -1) description = request.POST.get('description') ApiKeyModel().create(c.user.user_id, description, lifetime) Session().commit() h.flash(_("API key successfully created"), category='success') raise HTTPFound(location=url('edit_user_api_keys', id=c.user.user_id))
def canonical_hostname(): '''Return canonical hostname of system''' from kallithea import CONFIG try: parts = CONFIG.get('canonical_url', '').split('://', 1) return parts[1].split('/', 1)[0] except IndexError: parts = url('home', qualified=True).split('://', 1) return parts[1].split('/', 1)[0]
def delete(self, repo_name, revision, f_path): repo = c.db_repo if repo.enable_locking and repo.locked[0]: h.flash(_('This repository has been locked by %s on %s') % (h.person_by_id(repo.locked[0]), h.fmt_date(h.time_to_datetime(repo.locked[1]))), 'warning') raise HTTPFound(location=h.url('files_home', repo_name=repo_name, revision='tip')) # check if revision is a branch identifier- basically we cannot # create multiple heads via file editing _branches = repo.scm_instance.branches # check if revision is a branch name or branch hash if revision not in _branches.keys() + _branches.values(): h.flash(_('You can only delete files with revision ' 'being a valid branch'), category='warning') raise HTTPFound(location=h.url('files_home', repo_name=repo_name, revision='tip', f_path=f_path)) r_post = request.POST c.cs = self.__get_cs(revision) c.file = self.__get_filenode(c.cs, f_path) c.default_message = _('Deleted file %s via Kallithea') % (f_path) c.f_path = f_path node_path = f_path author = request.authuser.full_contact if r_post: message = r_post.get('message') or c.default_message try: nodes = { node_path: { 'content': '' } } self.scm_model.delete_nodes( user=request.authuser.user_id, repo=c.db_repo, message=message, nodes=nodes, parent_cs=c.cs, author=author, ) h.flash(_('Successfully deleted file %s') % f_path, category='success') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during commit'), category='error') raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name, revision='tip')) return render('files/files_delete.html')
def edit_fields(self, repo_name): c.repo_info = self._load_repo() c.repo_fields = RepositoryField.query() \ .filter(RepositoryField.repository == c.repo_info).all() c.active = 'fields' if request.POST: raise HTTPFound(location=url('repo_edit_fields')) return render('admin/repos/repo_edit.html')
def edit(self, gist_id, format='html'): c.gist = Gist.get_or_404(gist_id) if c.gist.is_expired: log.error('Gist expired at %s', time_to_datetime(c.gist.gist_expires)) raise HTTPNotFound() try: c.file_changeset, c.files = GistModel().get_gist_files(gist_id) except VCSError: log.error(traceback.format_exc()) raise HTTPNotFound() self.__load_defaults(extra_values=('0', _('Unmodified'))) rendered = render('admin/gists/edit.html') if request.POST: rpost = request.POST nodes = {} for org_filename, filename, mimetype, content in zip( rpost.getall('org_files'), rpost.getall('files'), rpost.getall('mimetypes'), rpost.getall('contents')): nodes[org_filename] = { 'org_filename': org_filename, 'filename': filename, 'content': content, 'lexer': mimetype, } try: GistModel().update( gist=c.gist, description=rpost['description'], owner=c.gist.owner, gist_mapping=nodes, gist_type=c.gist.gist_type, lifetime=rpost['lifetime'] ) Session().commit() h.flash(_('Successfully updated gist content'), category='success') except NodeNotChangedError: # raised if nothing was changed in repo itself. We anyway then # store only DB stuff for gist Session().commit() h.flash(_('Successfully updated gist data'), category='success') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of gist %s') % gist_id, category='error') raise HTTPFound(location=url('gist', gist_id=gist_id)) return rendered
def _redirect_to_login(message=None): """Return an exception that must be raised. It will redirect to the login page which will redirect back to the current URL after authentication. The optional message will be shown in a flash message.""" from kallithea.lib import helpers as h if message: h.flash(h.literal(message), category='warning') p = request.path_qs log.debug('Redirecting to login page, origin: %s', p) return HTTPFound(location=url('login_home', came_from=p))
def delete(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) #only owner can delete it ! if pull_request.owner_id == request.authuser.user_id: PullRequestModel().delete(pull_request) Session().commit() h.flash(_('Successfully deleted pull request'), category='success') raise HTTPFound(location=url('my_pullrequests')) raise HTTPForbidden()
def edit_permissions_update(self, repo_name): form = RepoPermsForm()().to_python(request.POST) RepoModel()._update_permissions(repo_name, form['perms_new'], form['perms_updates']) #TODO: implement this #action_logger(request.authuser, 'admin_changed_repo_permissions', # repo_name, request.ip_addr) Session().commit() h.flash(_('Repository permissions updated'), category='success') raise HTTPFound(location=url('edit_repo_perms', repo_name=repo_name))
def add_ip(self, id): ip = request.POST.get('new_ip') user_model = UserModel() try: user_model.add_extra_ip(id, ip) Session().commit() h.flash(_("Added IP address %s to user whitelist") % ip, category='success') except formencode.Invalid as error: msg = error.error_dict['ip'] h.flash(msg, category='error') except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred while adding IP address'), category='error') if 'default_user' in request.POST: raise HTTPFound(location=url('admin_permissions_ips')) raise HTTPFound(location=url('edit_user_ips', id=id))
def delete_repo_field(self, repo_name, field_id): field = RepositoryField.get_or_404(field_id) try: Session().delete(field) Session().commit() except Exception as e: log.error(traceback.format_exc()) msg = _('An error occurred during removal of field') h.flash(msg, category='error') raise HTTPFound(location=url('edit_repo_fields', repo_name=repo_name))
def delete(self, gist_id): gist = GistModel().get_gist(gist_id) owner = gist.owner_id == request.authuser.user_id if h.HasPermissionAny('hg.admin')() or owner: GistModel().delete(gist) Session().commit() h.flash(_('Deleted gist %s') % gist.gist_access_id, category='success') else: raise HTTPForbidden() raise HTTPFound(location=url('gists'))
def edit_caches(self, repo_name): c.repo_info = self._load_repo() c.active = 'caches' if request.POST: try: ScmModel().mark_for_invalidation(repo_name) Session().commit() h.flash(_('Cache invalidation successful'), category='success') except Exception as e: log.error(traceback.format_exc()) h.flash(_('An error occurred during cache invalidation'), category='error') raise HTTPFound( location=url('edit_repo_caches', repo_name=c.repo_name)) return render('admin/repos/repo_edit.html')
def get_pull_request(): from kallithea.model.db import PullRequest pull_request_id = action_params nice_id = PullRequest.make_nice_id(pull_request_id) deleted = user_log.repository is None if deleted: repo_name = user_log.repository_name else: repo_name = user_log.repository.repo_name return link_to( _('Pull request %s') % nice_id, url('pullrequest_show', repo_name=repo_name, pull_request_id=pull_request_id))
def edit_remote(self, repo_name): c.repo_info = self._load_repo() c.active = 'remote' if request.POST: try: ScmModel().pull_changes(repo_name, request.authuser.username, request.ip_addr) h.flash(_('Pulled from remote location'), category='success') except Exception as e: log.error(traceback.format_exc()) h.flash( _('An error occurred during pull from remote location'), category='error') raise HTTPFound( location=url('edit_repo_remote', repo_name=c.repo_name)) return render('admin/repos/repo_edit.html')
def update(self, repo_name): c.repo_info = self._load_repo() 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(request.authuser, 'admin_updated_repo', changed_name, request.ip_addr) Session().commit() except formencode.Invalid as errors: log.info(errors) defaults = self.__load_data() defaults.update(errors.value) 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 create(self, repo_name): repo = c.db_repo try: _form = PullRequestForm(repo.repo_id)().to_python(request.POST) except formencode.Invalid as errors: log.error(traceback.format_exc()) log.error(str(errors)) msg = _('Error creating pull request: %s') % errors.msg h.flash(msg, 'error') raise HTTPBadRequest # heads up: org and other might seem backward here ... org_ref = _form[ 'org_ref'] # will have merge_rev as rev but symbolic name org_repo = Repository.guess_instance(_form['org_repo']) other_ref = _form[ 'other_ref'] # will have symbolic name and head revision other_repo = Repository.guess_instance(_form['other_repo']) reviewers = [] title = _form['pullrequest_title'] description = _form['pullrequest_desc'].strip() owner = User.get(request.authuser.user_id) try: cmd = CreatePullRequestAction(org_repo, other_repo, org_ref, other_ref, title, description, owner, reviewers) except CreatePullRequestAction.ValidationError as e: h.flash(e, category='error', logf=log.error) raise HTTPNotFound try: pull_request = cmd.execute() Session().commit() except Exception: h.flash(_('Error occurred while creating pull request'), category='error') log.error(traceback.format_exc()) raise HTTPFound( location=url('pullrequest_home', repo_name=repo_name)) h.flash(_('Successfully opened new pull request'), category='success') raise HTTPFound(location=pull_request.url())
def settings_search(self): c.active = 'search' if request.POST: repo_location = self._get_hg_ui_settings()['paths_root_path'] full_index = request.POST.get('full_index', False) tasks.whoosh_index(repo_location, full_index) h.flash(_('Whoosh reindex task scheduled'), category='success') raise HTTPFound(location=url('admin_settings_search')) defaults = Setting.get_app_settings() defaults.update(self._get_hg_ui_settings()) return htmlfill.render( render('admin/settings/settings.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def add_email(self, id): user = self._get_user_or_raise_if_default(id) email = request.POST.get('new_email') user_model = UserModel() try: user_model.add_extra_email(id, email) Session().commit() h.flash(_("Added email %s to user") % email, category='success') except formencode.Invalid as error: msg = error.error_dict['email'] h.flash(msg, category='error') except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during email saving'), category='error') raise HTTPFound(location=url('edit_user_emails', id=id))
def index(self): c.came_from = safe_str(request.GET.get('came_from', '')) if c.came_from: if not self._validate_came_from(c.came_from): log.error('Invalid came_from (not server-relative): %r', c.came_from) raise HTTPBadRequest() else: c.came_from = url('home') ip_allowed = AuthUser.check_ip_allowed(request.authuser, request.ip_addr) # redirect if already logged in if request.authuser.is_authenticated and ip_allowed: raise HTTPFound(location=c.came_from) if request.POST: # import Login Form validator class login_form = LoginForm()() try: c.form_result = login_form.to_python(dict(request.POST)) # form checks for username/password, now we're authenticated username = c.form_result['username'] user = User.get_by_username_or_email(username, case_insensitive=True) except formencode.Invalid as errors: defaults = errors.value # remove password from filling in form again defaults.pop('password', None) return htmlfill.render( render('/login.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except UserCreationError as e: # container auth or other auth functions that create users on # the fly can throw this exception signaling that there's issue # with user creation, explanation should be provided in # Exception itself h.flash(e, 'error') else: log_in_user(user, c.form_result['remember'], is_external_auth=False) raise HTTPFound(location=c.came_from) return render('/login.html')
def settings_mapping(self): c.active = 'mapping' if request.POST: rm_obsolete = request.POST.get('destroy', False) install_git_hooks = request.POST.get('hooks', False) overwrite_git_hooks = request.POST.get('hooks_overwrite', False) invalidate_cache = request.POST.get('invalidate', False) log.debug('rescanning repo location with destroy obsolete=%s, ' 'install git hooks=%s and ' 'overwrite git hooks=%s' % (rm_obsolete, install_git_hooks, overwrite_git_hooks)) filesystem_repos = ScmModel().repo_scan() added, removed = repo2db_mapper(filesystem_repos, rm_obsolete, install_git_hooks=install_git_hooks, user=request.authuser.username, overwrite_git_hooks=overwrite_git_hooks) added_msg = h.HTML(', ').join( h.link_to(safe_str(repo_name), h.url('summary_home', repo_name=repo_name)) for repo_name in added ) or '-' removed_msg = h.HTML(', ').join( safe_str(repo_name) for repo_name in removed ) or '-' h.flash(h.HTML(_('Repositories successfully rescanned. Added: %s. Removed: %s.')) % (added_msg, removed_msg), category='success') if invalidate_cache: log.debug('invalidating all repositories cache') i = 0 for repo in Repository.query(): try: ScmModel().mark_for_invalidation(repo.repo_name) i += 1 except VCSError as e: log.warning('VCS error invalidating %s: %s', repo.repo_name, e) h.flash(_('Invalidated %s repositories') % i, category='success') raise HTTPFound(location=url('admin_settings_mapping')) defaults = Setting.get_app_settings() defaults.update(self._get_hg_ui_settings()) return htmlfill.render( render('admin/settings/settings.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def settings_global(self): c.active = 'global' if request.POST: application_form = ApplicationSettingsForm()() try: form_result = application_form.to_python(dict(request.POST)) except formencode.Invalid as errors: return htmlfill.render( render('admin/settings/settings.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) try: for setting in ( 'title', 'realm', 'ga_code', 'captcha_public_key', 'captcha_private_key', ): Setting.create_or_update(setting, form_result[setting]) Session().commit() set_app_settings(config) h.flash(_('Updated application settings'), category='success') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred while updating ' 'application settings'), category='error') raise HTTPFound(location=url('admin_settings_global')) defaults = Setting.get_app_settings() defaults.update(self._get_hg_ui_settings()) return htmlfill.render( render('admin/settings/settings.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def update(self, id): c.user_group = UserGroup.get_or_404(id) c.active = 'settings' self.__load_data(id) available_members = [safe_str(x[0]) for x in c.available_members] users_group_form = UserGroupForm(edit=True, old_data=c.user_group.get_dict(), available_members=available_members)() try: form_result = users_group_form.to_python(request.POST) UserGroupModel().update(c.user_group, form_result) gr = form_result['users_group_name'] action_logger(request.authuser, 'admin_updated_users_group:%s' % gr, None, request.ip_addr) h.flash(_('Updated user group %s') % gr, category='success') Session().commit() except formencode.Invalid as errors: ug_model = UserGroupModel() defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': ug_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': ug_model.has_perm(id, 'hg.fork.repository'), }) return htmlfill.render( render('admin/user_groups/user_group_edit.html'), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of user group %s') % request.POST.get('users_group_name'), category='error') raise HTTPFound(location=url('edit_users_group', id=id))
def toggle_locking(self, repo_name): try: repo = Repository.get_by_repo_name(repo_name) if repo.enable_locking: if repo.locked[0]: Repository.unlock(repo) h.flash(_('Repository has been unlocked'), category='success') else: Repository.lock(repo, request.authuser.user_id) h.flash(_('Repository has been locked'), category='success') except Exception as e: log.error(traceback.format_exc()) h.flash(_('An error occurred during unlocking'), category='error') raise HTTPFound(location=url('summary_home', repo_name=repo_name))
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 edit_advanced_locking(self, repo_name): """ Unlock repository when it is locked ! :param repo_name: """ try: repo = Repository.get_by_repo_name(repo_name) if request.POST.get('set_lock'): Repository.lock(repo, request.authuser.user_id) h.flash(_('Repository has been locked'), category='success') elif request.POST.get('set_unlock'): Repository.unlock(repo) h.flash(_('Repository has been unlocked'), category='success') except Exception as e: log.error(traceback.format_exc()) h.flash(_('An error occurred during unlocking'), category='error') raise HTTPFound( location=url('edit_repo_advanced', repo_name=repo_name))
def create_repo_field(self, repo_name): try: form_result = RepoFieldForm()().to_python(dict(request.POST)) new_field = RepositoryField() new_field.repository = Repository.get_by_repo_name(repo_name) new_field.field_key = form_result['new_field_key'] new_field.field_type = form_result['new_field_type'] # python type new_field.field_value = form_result[ 'new_field_value'] # set initial blank value new_field.field_desc = form_result['new_field_desc'] new_field.field_label = form_result['new_field_label'] Session().add(new_field) Session().commit() except formencode.Invalid as e: h.flash(_('Field validation error: %s') % e.msg, category='error') except Exception as e: log.error(traceback.format_exc()) h.flash(_('An error occurred during creation of field: %r') % e, category='error') raise HTTPFound(location=url('edit_repo_fields', repo_name=repo_name))
def url_func(changeset): author = escape(changeset.author) date = changeset.date message = escape(changeset.message) tooltip_html = ("<b>Author:</b> %s<br/>" "<b>Date:</b> %s</b><br/>" "<b>Message:</b> %s") % (author, date, message) lnk_format = show_id(changeset) uri = link_to( lnk_format, url('changeset_home', repo_name=repo_name, revision=changeset.raw_id), style=get_color_string(changeset.raw_id), **{'data-toggle': 'popover', 'data-content': tooltip_html} ) uri += '\n' return uri
def __load_data(self): """ Load defaults settings for edit, and update """ self.__load_defaults() c.repo_info = c.db_repo repo = c.db_repo.scm_instance if c.repo_info is None: h.not_mapped_error(c.repo_name) raise HTTPFound(location=url('repos')) c.default_user_id = User.get_default_user().user_id c.in_public_journal = UserFollowing.query() \ .filter(UserFollowing.user_id == c.default_user_id) \ .filter(UserFollowing.follows_repository == c.repo_info).scalar() if c.repo_info.stats: last_rev = c.repo_info.stats.stat_on_revision + 1 else: last_rev = 0 c.stats_revision = last_rev c.repo_last_rev = repo.count() if repo.revisions else 0 if last_rev == 0 or c.repo_last_rev == 0: c.stats_percentage = 0 else: c.stats_percentage = '%.2f' % ((float( (last_rev)) / c.repo_last_rev) * 100) defaults = RepoModel()._get_defaults(c.repo_name) # alter the description to indicate a fork defaults['description'] = ( 'fork of repository: %s \n%s' % (defaults['repo_name'], defaults['description'])) # add suffix to fork defaults['repo_name'] = '%s-fork' % defaults['repo_name'] return defaults
def password_reset_confirmation(self): # This controller handles both GET and POST requests, though we # only ever perform the actual password change on POST (since # GET requests are not allowed to have side effects, and do not # receive automatic CSRF protection). # The template needs the email address outside of the form. c.email = request.params.get('email') if not request.POST: return htmlfill.render( render('/password_reset_confirmation.html'), defaults=dict(request.params), encoding='UTF-8') form = PasswordResetConfirmationForm()() try: form_result = form.to_python(dict(request.POST)) except formencode.Invalid as errors: return htmlfill.render( render('/password_reset_confirmation.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding='UTF-8') if not UserModel().verify_reset_password_token( form_result['email'], form_result['timestamp'], form_result['token'], ): return htmlfill.render( render('/password_reset_confirmation.html'), defaults=form_result, errors={'token': _('Invalid password reset token')}, prefix_error=False, encoding='UTF-8') UserModel().reset_password(form_result['email'], form_result['password']) h.flash(_('Successfully updated password'), category='success') raise HTTPFound(location=url('login_home'))
def edit_advanced_journal(self, repo_name): """ Sets this repository to be visible in public journal, in other words asking default user to follow this repo :param repo_name: """ try: repo_id = Repository.get_by_repo_name(repo_name).repo_id user_id = kallithea.DEFAULT_USER_ID self.scm_model.toggle_following_repo(repo_id, user_id) h.flash(_('Updated repository visibility in public journal'), category='success') Session().commit() except Exception: h.flash(_('An error occurred during setting this' ' repository in public journal'), category='error') raise HTTPFound( location=url('edit_repo_advanced', repo_name=repo_name))
def _replace(match_obj): url = match_obj.group('url') if url is not None: return '<a href="%(url)s">%(url)s</a>' % {'url': url} mention = match_obj.group('mention') if mention is not None: return '<b>%s</b>' % mention hash_ = match_obj.group('hash') if hash_ is not None and repo_name is not None: from kallithea.config.routing import url # doh, we need to re-import url to mock it later return '<a class="revision-link" href="%(url)s">%(hash)s</a>' % { 'url': url( 'changeset_home', repo_name=repo_name, revision=hash_), 'hash': hash_, } bold = match_obj.group('bold') if bold is not None: return '<b>*%s*</b>' % _urlify(bold[1:-1]) if stylize: seen = match_obj.group('seen') if seen: return '<div class="metatag" data-tag="see">see => %s</div>' % seen license = match_obj.group('license') if license: return '<div class="metatag" data-tag="license"><a href="http:\/\/www.opensource.org/licenses/%s">%s</a></div>' % ( license, license) tagtype = match_obj.group('tagtype') if tagtype: tagvalue = match_obj.group('tagvalue') return '<div class="metatag" data-tag="%s">%s => <a href="/%s">%s</a></div>' % ( tagtype, tagtype, tagvalue, tagvalue) lang = match_obj.group('lang') if lang: return '<div class="metatag" data-tag="lang">%s</div>' % lang tag = match_obj.group('tag') if tag: return '<div class="metatag" data-tag="%s">%s</div>' % (tag, tag) return match_obj.group(0)
def update_default_perms(self, id): user_group = UserGroup.get_or_404(id) try: form = CustomDefaultPermissionsForm()() form_result = form.to_python(request.POST) inherit_perms = form_result['inherit_default_permissions'] user_group.inherit_default_permissions = inherit_perms usergroup_model = UserGroupModel() defs = UserGroupToPerm.query() \ .filter(UserGroupToPerm.users_group == user_group) \ .all() for ug in defs: Session().delete(ug) if form_result['create_repo_perm']: usergroup_model.grant_perm(id, 'hg.create.repository') else: usergroup_model.grant_perm(id, 'hg.create.none') if form_result['create_user_group_perm']: usergroup_model.grant_perm(id, 'hg.usergroup.create.true') else: usergroup_model.grant_perm(id, 'hg.usergroup.create.false') if form_result['fork_repo_perm']: usergroup_model.grant_perm(id, 'hg.fork.repository') else: usergroup_model.grant_perm(id, 'hg.fork.none') h.flash(_("Updated permissions"), category='success') Session().commit() except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during permissions saving'), category='error') raise HTTPFound(location=url('edit_user_group_default_perms', id=id))
def _before(self, *args, **kwargs): super(BaseRepoController, self)._before(*args, **kwargs) if c.repo_name: # extracted from request by base-base BaseController._before _dbr = Repository.get_by_repo_name(c.repo_name) if not _dbr: return log.debug('Found repository in database %s with state `%s`', _dbr, _dbr.repo_state) route = getattr(request.environ.get('routes.route'), 'name', '') # allow to delete repos that are somehow damages in filesystem if route in ['delete_repo']: return if _dbr.repo_state in [Repository.STATE_PENDING]: if route in ['repo_creating_home']: return check_url = url('repo_creating_home', repo_name=c.repo_name) raise webob.exc.HTTPFound(location=check_url) dbr = c.db_repo = _dbr c.db_repo_scm_instance = c.db_repo.scm_instance if c.db_repo_scm_instance is None: log.error( '%s this repository is present in database but it ' 'cannot be created as an scm instance', c.repo_name) from kallithea.lib import helpers as h h.flash(_('Repository not found in the filesystem'), category='error') raise webob.exc.HTTPNotFound() # some globals counter for menu c.repository_followers = self.scm_model.get_followers(dbr) c.repository_forks = self.scm_model.get_forks(dbr) c.repository_pull_requests = self.scm_model.get_pull_requests(dbr) c.repository_following = self.scm_model.is_following_repo( c.repo_name, request.authuser.user_id)
def update(self, id): user_model = UserModel() user = user_model.get(id) _form = UserForm(edit=True, old_data={'user_id': id, 'email': user.email})() form_result = {} try: form_result = _form.to_python(dict(request.POST)) skip_attrs = ['extern_type', 'extern_name', ] + auth_modules.get_managed_fields(user) user_model.update(id, form_result, skip_attrs=skip_attrs) usr = form_result['username'] action_logger(request.authuser, 'admin_updated_user:%s' % usr, None, request.ip_addr) h.flash(_('User updated successfully'), category='success') Session().commit() except formencode.Invalid as errors: defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'), }) return htmlfill.render( self._render_edit_profile(user), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of user %s') \ % form_result.get('username'), category='error') raise HTTPFound(location=url('edit_user', id=id))
def edit_advanced(self, repo_name): c.repo_info = self._load_repo() c.default_user_id = User.get_default_user().user_id c.in_public_journal = UserFollowing.query() \ .filter(UserFollowing.user_id == c.default_user_id) \ .filter(UserFollowing.follows_repository == c.repo_info).scalar() _repos = Repository.query(sorted=True).all() read_access_repos = RepoList(_repos, perm_level='read') c.repos_list = [(None, _('-- Not a fork --'))] c.repos_list += [(x.repo_id, x.repo_name) for x in read_access_repos if x.repo_id != c.repo_info.repo_id] defaults = { 'id_fork_of': c.repo_info.fork_id if c.repo_info.fork_id else '' } c.active = 'advanced' if request.POST: raise HTTPFound(location=url('repo_edit_advanced')) return htmlfill.render(render('admin/repos/repo_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def url_generator(**kw): return url('changelog_summary_home', repo_name=c.db_repo.repo_name, size=size, **kw)
def get_fork_name(): repo_name = action_params url_ = url('summary_home', repo_name=repo_name) return _('Fork name %s') % link_to(action_params, url_)
def get_cs_links(): revs_limit = 3 # display this amount always revs_top_limit = 50 # show upto this amount of changesets hidden revs_ids = action_params.split(',') deleted = user_log.repository is None if deleted: return ','.join(revs_ids) repo_name = user_log.repository.repo_name def lnk(rev, repo_name): lazy_cs = False title_ = None url_ = '#' if isinstance(rev, BaseChangeset) or isinstance(rev, AttributeDict): if rev.op and rev.ref_name: if rev.op == 'delete_branch': lbl = _('Deleted branch: %s') % rev.ref_name elif rev.op == 'tag': lbl = _('Created tag: %s') % rev.ref_name else: lbl = 'Unknown operation %s' % rev.op else: lazy_cs = True lbl = rev.short_id[:8] url_ = url('changeset_home', repo_name=repo_name, revision=rev.raw_id) else: # changeset cannot be found - it might have been stripped or removed lbl = rev[:12] title_ = _('Changeset %s not found') % lbl if parse_cs: return link_to(lbl, url_, title=title_, **{'data-toggle': 'tooltip'}) return link_to(lbl, url_, class_='lazy-cs' if lazy_cs else '', **{'data-raw_id': rev.raw_id, 'data-repo_name': repo_name}) def _get_op(rev_txt): _op = None _name = rev_txt if len(rev_txt.split('=>')) == 2: _op, _name = rev_txt.split('=>') return _op, _name revs = [] if len([v for v in revs_ids if v != '']) > 0: repo = None for rev in revs_ids[:revs_top_limit]: _op, _name = _get_op(rev) # we want parsed changesets, or new log store format is bad if parse_cs: try: if repo is None: repo = user_log.repository.scm_instance _rev = repo.get_changeset(rev) revs.append(_rev) except ChangesetDoesNotExistError: log.error('cannot find revision %s in this repo', rev) revs.append(rev) else: _rev = AttributeDict({ 'short_id': rev[:12], 'raw_id': rev, 'message': '', 'op': _op, 'ref_name': _name }) revs.append(_rev) cs_links = [" " + ', '.join( [lnk(rev, repo_name) for rev in revs[:revs_limit]] )] _op1, _name1 = _get_op(revs_ids[0]) _op2, _name2 = _get_op(revs_ids[-1]) _rev = '%s...%s' % (_name1, _name2) compare_view = ( ' <div class="compare_view" data-toggle="tooltip" title="%s">' '<a href="%s">%s</a> </div>' % ( _('Show all combined changesets %s->%s') % ( revs_ids[0][:12], revs_ids[-1][:12] ), url('changeset_home', repo_name=repo_name, revision=_rev ), _('Compare view') ) ) # if we have exactly one more than normally displayed # just display it, takes less space than displaying # "and 1 more revisions" if len(revs_ids) == revs_limit + 1: cs_links.append(", " + lnk(revs[revs_limit], repo_name)) # hidden-by-default ones if len(revs_ids) > revs_limit + 1: uniq_id = revs_ids[0] html_tmpl = ( '<span> %s <a class="show_more" id="_%s" ' 'href="#more">%s</a> %s</span>' ) if not feed: cs_links.append(html_tmpl % ( _('and'), uniq_id, _('%s more') % (len(revs_ids) - revs_limit), _('revisions') ) ) if not feed: html_tmpl = '<span id="%s" style="display:none">, %s </span>' else: html_tmpl = '<span id="%s"> %s </span>' morelinks = ', '.join( [lnk(rev, repo_name) for rev in revs[revs_limit:]] ) if len(revs_ids) > revs_top_limit: morelinks += ', ...' cs_links.append(html_tmpl % (uniq_id, morelinks)) if len(revs) > 1: cs_links.append(compare_view) return ''.join(cs_links)
def permission_globals(self): c.active = 'globals' self.__load_data() if request.POST: _form = DefaultPermissionsForm( [x[0] for x in c.repo_perms_choices], [x[0] for x in c.group_perms_choices], [x[0] for x in c.user_group_perms_choices], [x[0] for x in c.repo_create_choices], [x[0] for x in c.repo_create_on_write_choices], [x[0] for x in c.repo_group_create_choices], [x[0] for x in c.user_group_create_choices], [x[0] for x in c.fork_choices], [x[0] for x in c.register_choices], [x[0] for x in c.extern_activate_choices])() try: form_result = _form.to_python(dict(request.POST)) form_result.update({'perm_user_name': 'default'}) PermissionModel().update(form_result) Session().commit() h.flash(_('Global permissions updated successfully'), category='success') except formencode.Invalid as errors: defaults = errors.value return htmlfill.render( render('admin/permissions/permissions.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 permissions'), category='error') raise HTTPFound(location=url('admin_permissions')) c.user = User.get_default_user() defaults = {'anonymous': c.user.active} for p in c.user.user_perms: if p.permission.permission_name.startswith('repository.'): defaults['default_repo_perm'] = p.permission.permission_name if p.permission.permission_name.startswith('group.'): defaults['default_group_perm'] = p.permission.permission_name if p.permission.permission_name.startswith('usergroup.'): defaults[ 'default_user_group_perm'] = p.permission.permission_name if p.permission.permission_name.startswith( 'hg.create.write_on_repogroup.'): defaults['create_on_write'] = p.permission.permission_name elif p.permission.permission_name.startswith('hg.create.'): defaults['default_repo_create'] = p.permission.permission_name if p.permission.permission_name.startswith('hg.repogroup.'): defaults[ 'default_repo_group_create'] = p.permission.permission_name if p.permission.permission_name.startswith('hg.usergroup.'): defaults[ 'default_user_group_create'] = p.permission.permission_name if p.permission.permission_name.startswith('hg.register.'): defaults['default_register'] = p.permission.permission_name if p.permission.permission_name.startswith('hg.extern_activate.'): defaults[ 'default_extern_activate'] = p.permission.permission_name if p.permission.permission_name.startswith('hg.fork.'): defaults['default_fork'] = p.permission.permission_name return htmlfill.render(render('admin/permissions/permissions.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def index(self, repo_name, revision=None, f_path=None): # Fix URL after page size form submission via GET # TODO: Somehow just don't send this extra junk in the GET URL if request.GET.get('set'): request.GET.pop('set', None) if revision is None: raise HTTPFound(location=url( 'changelog_home', repo_name=repo_name, **request.GET)) raise HTTPFound(location=url('changelog_file_home', repo_name=repo_name, revision=revision, f_path=f_path, **request.GET)) limit = 2000 default = 100 if request.GET.get('size'): c.size = max(min(safe_int(request.GET.get('size')), limit), 1) session['changelog_size'] = c.size session.save() else: c.size = int(session.get('changelog_size', default)) # min size must be 1 c.size = max(c.size, 1) p = safe_int(request.GET.get('page'), 1) branch_name = request.GET.get('branch', None) if (branch_name and branch_name not in c.db_repo_scm_instance.branches and branch_name not in c.db_repo_scm_instance.closed_branches and not revision): raise HTTPFound(location=url('changelog_file_home', repo_name=c.repo_name, revision=branch_name, f_path=f_path or '')) if revision == 'tip': revision = None c.changelog_for_path = f_path try: if f_path: log.debug('generating changelog for path %s', f_path) # get the history for the file ! tip_cs = c.db_repo_scm_instance.get_changeset() try: collection = tip_cs.get_file_history(f_path) except (NodeDoesNotExistError, ChangesetError): #this node is not present at tip ! try: cs = self.__get_cs(revision, repo_name) collection = cs.get_file_history(f_path) except RepositoryError as e: h.flash(safe_str(e), category='warning') raise HTTPFound(location=h.url('changelog_home', repo_name=repo_name)) collection = list(reversed(collection)) else: collection = c.db_repo_scm_instance.get_changesets( start=0, end=revision, branch_name=branch_name) c.total_cs = len(collection) c.pagination = RepoPage( collection, page=p, item_count=c.total_cs, items_per_page=c.size, branch=branch_name, ) page_revisions = [x.raw_id for x in c.pagination] c.comments = c.db_repo.get_comments(page_revisions) c.statuses = c.db_repo.statuses(page_revisions) except EmptyRepositoryError as e: h.flash(safe_str(e), category='warning') raise HTTPFound( location=url('summary_home', repo_name=c.repo_name)) except (RepositoryError, ChangesetDoesNotExistError, Exception) as e: log.error(traceback.format_exc()) h.flash(safe_str(e), category='error') raise HTTPFound( location=url('changelog_home', repo_name=c.repo_name)) c.branch_name = branch_name c.branch_filters = [('', _('None'))] + \ [(k, k) for k in c.db_repo_scm_instance.branches.keys()] if c.db_repo_scm_instance.closed_branches: prefix = _('(closed)') + ' ' c.branch_filters += [('-', '-')] + \ [(k, prefix + k) for k in c.db_repo_scm_instance.closed_branches.keys()] revs = [] if not f_path: revs = [x.revision for x in c.pagination] c.jsdata = graph_data(c.db_repo_scm_instance, revs) c.revision = revision # requested revision ref c.first_revision = c.pagination[0] # pagination is never empty here! return render('changelog/changelog.html')
def diff(self, repo_name, f_path): ignore_whitespace = request.GET.get('ignorews') == '1' line_context = safe_int(request.GET.get('context'), 3) diff2 = request.GET.get('diff2', '') diff1 = request.GET.get('diff1', '') or diff2 c.action = request.GET.get('diff') c.no_changes = diff1 == diff2 c.f_path = f_path c.big_diff = False fulldiff = request.GET.get('fulldiff') c.anchor_url = anchor_url c.ignorews_url = _ignorews_url c.context_url = _context_url c.changes = OrderedDict() c.changes[diff2] = [] # special case if we want a show rev only, it's impl here # to reduce JS and callbacks if request.GET.get('show_rev'): if str2bool(request.GET.get('annotate', 'False')): _url = url('files_annotate_home', repo_name=c.repo_name, revision=diff1, f_path=c.f_path) else: _url = url('files_home', repo_name=c.repo_name, revision=diff1, f_path=c.f_path) raise HTTPFound(location=_url) try: if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_1 = c.db_repo_scm_instance.get_changeset(diff1) try: node1 = c.changeset_1.get_node(f_path) if node1.is_dir(): raise NodeError('%s path is a %s not a file' % (node1, type(node1))) except NodeDoesNotExistError: c.changeset_1 = EmptyChangeset( cs=diff1, revision=c.changeset_1.revision, repo=c.db_repo_scm_instance) node1 = FileNode(f_path, '', changeset=c.changeset_1) else: c.changeset_1 = EmptyChangeset(repo=c.db_repo_scm_instance) node1 = FileNode(f_path, '', changeset=c.changeset_1) if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: c.changeset_2 = c.db_repo_scm_instance.get_changeset(diff2) try: node2 = c.changeset_2.get_node(f_path) if node2.is_dir(): raise NodeError('%s path is a %s not a file' % (node2, type(node2))) except NodeDoesNotExistError: c.changeset_2 = EmptyChangeset( cs=diff2, revision=c.changeset_2.revision, repo=c.db_repo_scm_instance) node2 = FileNode(f_path, '', changeset=c.changeset_2) else: c.changeset_2 = EmptyChangeset(repo=c.db_repo_scm_instance) node2 = FileNode(f_path, '', changeset=c.changeset_2) except (RepositoryError, NodeError): log.error(traceback.format_exc()) raise HTTPFound(location=url( 'files_home', repo_name=c.repo_name, f_path=f_path)) if c.action == 'download': raw_diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) diff_name = '%s_vs_%s.diff' % (diff1, diff2) response.content_type = 'text/plain' response.content_disposition = ('attachment; filename=%s' % diff_name) return raw_diff elif c.action == 'raw': raw_diff = diffs.get_gitdiff(node1, node2, ignore_whitespace=ignore_whitespace, context=line_context) response.content_type = 'text/plain' return raw_diff else: fid = h.FID(diff2, node2.path) line_context_lcl = get_line_ctx(fid, request.GET) ign_whitespace_lcl = get_ignore_ws(fid, request.GET) diff_limit = None if fulldiff else self.cut_off_limit c.a_rev, c.cs_rev, a_path, diff, st, op = diffs.wrapped_diff( filenode_old=node1, filenode_new=node2, diff_limit=diff_limit, ignore_whitespace=ign_whitespace_lcl, line_context=line_context_lcl, enable_comments=False) c.file_diff_data = [(fid, fid, op, a_path, node2.path, diff, st)] return render('files/file_diff.html')