Blame progit/issues.py

Pierre-Yves Chibon 47950c
#-*- coding: utf-8 -*-
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
"""
Pierre-Yves Chibon 47950c
 (c) 2014 - Copyright Red Hat Inc
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
 Authors:
Pierre-Yves Chibon 47950c
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
"""
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
import flask
Pierre-Yves Chibon 47950c
import os
Pierre-Yves Chibon 47950c
from math import ceil
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
import pygit2
Pierre-Yves Chibon 47950c
from sqlalchemy.exc import SQLAlchemyError
Pierre-Yves Chibon 47950c
from pygments import highlight
Pierre-Yves Chibon 47950c
from pygments.lexers import guess_lexer
Pierre-Yves Chibon 47950c
from pygments.lexers.text import DiffLexer
Pierre-Yves Chibon 47950c
from pygments.formatters import HtmlFormatter
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
import progit.doc_utils
Pierre-Yves Chibon 47950c
import progit.lib
Pierre-Yves Chibon 47950c
import progit.forms
Pierre-Yves Chibon 47950c
from progit import APP, SESSION, LOG, __get_file_in_tree, cla_required
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
def do_new_issue(repo, username=None):
Pierre-Yves Chibon 47950c
    """ Create a new issue
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if repo is None:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    form = progit.forms.IssueForm()
Pierre-Yves Chibon 47950c
    if form.validate_on_submit():
Pierre-Yves Chibon 47950c
        title = form.title.data
Pierre-Yves Chibon 47950c
        content = form.content.data
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
        try:
Pierre-Yves Chibon 47950c
            message = progit.lib.new_issue(
Pierre-Yves Chibon 47950c
                SESSION,
Pierre-Yves Chibon 47950c
                repo=repo,
Pierre-Yves Chibon 47950c
                title=title,
Pierre-Yves Chibon 47950c
                content=content,
Pierre-Yves Chibon 47950c
                user=flask.g.fas_user.username,
Pierre-Yves Chibon 47950c
            )
Pierre-Yves Chibon 47950c
            SESSION.commit()
Pierre-Yves Chibon 47950c
            flask.flash(message)
Pierre-Yves Chibon 47950c
            return flask.redirect(flask.url_for(
Pierre-Yves Chibon 47950c
                'view_fork_issues', username=username, repo=repo.name))
Pierre-Yves Chibon 47950c
        except progit.exceptions.ProgitException, err:
Pierre-Yves Chibon 47950c
            flask.flash(str(err), 'error')
Pierre-Yves Chibon 47950c
        except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon 47950c
            SESSION.rollback()
Pierre-Yves Chibon 47950c
            flask.flash(str(err), 'error')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'new_issue.html',
Pierre-Yves Chibon 47950c
        select='issues',
Pierre-Yves Chibon 47950c
        form=form,
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
def do_edit_issue(repo, issueid, username=None):
Pierre-Yves Chibon 47950c
    """ Edit the specified issue
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if repo is None:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not repo.issue_tracker:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'No issue tracker found for this project')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    issue = progit.lib.get_issue(SESSION, issueid)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if issue is None:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Issue not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    status = progit.lib.get_issue_statuses(SESSION)
Pierre-Yves Chibon 47950c
    form = progit.forms.IssueForm(status=status)
Pierre-Yves Chibon 47950c
    if form.validate_on_submit():
Pierre-Yves Chibon 47950c
        title = form.title.data
Pierre-Yves Chibon 47950c
        content = form.content.data
Pierre-Yves Chibon 47950c
        status = form.status.data
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
        try:
Pierre-Yves Chibon 47950c
            message = progit.lib.edit_issue(
Pierre-Yves Chibon 47950c
                SESSION,
Pierre-Yves Chibon 47950c
                issue=issue,
Pierre-Yves Chibon 47950c
                title=title,
Pierre-Yves Chibon 47950c
                content=content,
Pierre-Yves Chibon 47950c
                status=status,
Pierre-Yves Chibon 47950c
            )
Pierre-Yves Chibon 47950c
            SESSION.commit()
Pierre-Yves Chibon 47950c
            flask.flash(message)
Pierre-Yves Chibon 47950c
            url = flask.url_for('view_issues', repo=repo.name)
Pierre-Yves Chibon 47950c
            if username:
Pierre-Yves Chibon 47950c
                url = flask.url_for(
Pierre-Yves Chibon 47950c
                    'view_fork_issues', username=username, repo=repo.name)
Pierre-Yves Chibon 47950c
            return flask.redirect(url)
Pierre-Yves Chibon 47950c
        except progit.exceptions.ProgitException, err:
Pierre-Yves Chibon 47950c
            flask.flash(str(err), 'error')
Pierre-Yves Chibon 47950c
        except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon 47950c
            SESSION.rollback()
Pierre-Yves Chibon 47950c
            flask.flash(str(err), 'error')
Pierre-Yves Chibon 47950c
    elif flask.request.method == 'GET':
Pierre-Yves Chibon 47950c
        form.title.data = issue.title
Pierre-Yves Chibon 47950c
        form.content.data = issue.content
Pierre-Yves Chibon 47950c
        form.status.data = issue.status
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'new_issue.html',
Pierre-Yves Chibon 47950c
        select='issues',
Pierre-Yves Chibon 47950c
        type='edit',
Pierre-Yves Chibon 47950c
        form=form,
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        issue=issue,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
def do_view_issue(repo, issueid, username=None):
Pierre-Yves Chibon 47950c
    """ List all issues associated to a repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if repo is None:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not repo.issue_tracker:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'No issue tracker found for this project')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    issue = progit.lib.get_issue(SESSION, issueid)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if issue is None:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Issue not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    status = progit.lib.get_issue_statuses(SESSION)
Pierre-Yves Chibon 47950c
    form = progit.forms.UpdateIssueStatusForm(status=status)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if form.validate_on_submit():
Pierre-Yves Chibon 47950c
        try:
Pierre-Yves Chibon 47950c
            message = progit.lib.edit_issue(
Pierre-Yves Chibon 47950c
                SESSION,
Pierre-Yves Chibon 47950c
                issue=issue,
Pierre-Yves Chibon 47950c
                status=form.status.data,
Pierre-Yves Chibon 47950c
            )
Pierre-Yves Chibon 47950c
            SESSION.commit()
Pierre-Yves Chibon 47950c
            flask.flash(message)
Pierre-Yves Chibon 47950c
            url = flask.url_for('view_issues', repo=repo.name)
Pierre-Yves Chibon 47950c
            if username:
Pierre-Yves Chibon 47950c
                url = flask.url_for(
Pierre-Yves Chibon 47950c
                    'view_fork_issues', username=username, repo=repo.name)
Pierre-Yves Chibon 47950c
            return flask.redirect(url)
Pierre-Yves Chibon 47950c
        except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon 47950c
            SESSION.rollback()
Pierre-Yves Chibon 47950c
            flask.flash(str(err), 'error')
Pierre-Yves Chibon 47950c
    elif flask.request.method == 'GET':
Pierre-Yves Chibon 47950c
        form.status.data = issue.status
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'issue.html',
Pierre-Yves Chibon 47950c
        select='issues',
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        issue=issue,
Pierre-Yves Chibon 47950c
        form=form,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
def do_view_issues(repo, username=None, status=None):
Pierre-Yves Chibon 47950c
    """ List all issues associated to a repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if repo is None:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not repo.issue_tracker:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'No issue tracker found for this project')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if status is not None:
Pierre-Yves Chibon 47950c
        if status.lower() == 'closed':
Pierre-Yves Chibon 47950c
            issues = progit.lib.get_issues(SESSION, repo, closed=True)
Pierre-Yves Chibon 47950c
        else:
Pierre-Yves Chibon 47950c
            issues = progit.lib.get_issues(SESSION, repo, status=status)
Pierre-Yves Chibon 47950c
    else:
Pierre-Yves Chibon 47950c
        issues = progit.lib.get_issues(SESSION, repo, status='Open')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'issues.html',
Pierre-Yves Chibon 47950c
        select='issues',
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        status=status,
Pierre-Yves Chibon 47950c
        issues=issues,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
## URLs
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/<repo>/issues')</repo>
Pierre-Yves Chibon 47950c
def view_issues(repo):
Pierre-Yves Chibon 47950c
    """ List all issues associated to a repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    status = flask.request.args.get('status', None)
Pierre-Yves Chibon 47950c
    return do_view_issues(repo, status=status)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/fork/<username>/<repo>/issues')</repo></username>
Pierre-Yves Chibon 47950c
def view_fork_issues(repo, username):
Pierre-Yves Chibon 47950c
    """ List all issues associated to a repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    status = flask.request.args.get('status', None)
Pierre-Yves Chibon 47950c
    return do_view_issues(repo, username=username, status=status)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/<repo>/new_issue', methods=('GET', 'POST'))</repo>
Pierre-Yves Chibon 47950c
@cla_required
Pierre-Yves Chibon 47950c
def new_issue(repo):
Pierre-Yves Chibon 47950c
    """ Create a new issue
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_new_issue(repo)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/fork/<username>/<repo>/new_issue', methods=('GET', 'POST'))</repo></username>
Pierre-Yves Chibon 47950c
@cla_required
Pierre-Yves Chibon 47950c
def fork_new_issue(username, repo):
Pierre-Yves Chibon 47950c
    """ Create a new issue
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_new_issue(repo, username=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/<repo>/issue/<issueid>', methods=('GET', 'POST'))</issueid></repo>
Pierre-Yves Chibon 47950c
@cla_required
Pierre-Yves Chibon 47950c
def view_issue(repo, issueid):
Pierre-Yves Chibon 47950c
    """ List all issues associated to a repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_view_issue(repo, issueid)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/fork/<username>/<repo>/issue/<issueid>',</issueid></repo></username>
Pierre-Yves Chibon 47950c
           methods=('GET', 'POST'))
Pierre-Yves Chibon 47950c
@cla_required
Pierre-Yves Chibon 47950c
def view_fork_issue(username, repo, issueid):
Pierre-Yves Chibon 47950c
    """ List all issues associated to a repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_view_issue(repo, issueid, username=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/<repo>/issue/<issueid>/edit', methods=('GET', 'POST'))</issueid></repo>
Pierre-Yves Chibon 47950c
@cla_required
Pierre-Yves Chibon 47950c
def edit_issue(repo, issueid):
Pierre-Yves Chibon 47950c
    """ Edit the specified issue
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_edit_issue(repo, issueid)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/fork/<username>/<repo>/issue/<issueid>/edit',</issueid></repo></username>
Pierre-Yves Chibon 47950c
           methods=('GET', 'POST'))
Pierre-Yves Chibon 47950c
@cla_required
Pierre-Yves Chibon 47950c
def fork_edit_issue(username, repo, issueid):
Pierre-Yves Chibon 47950c
    """ Edit the specified issue opened against a fork
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_edit_issue(repo, issueid, username=username)
Pierre-Yves Chibon 47950c