Blame progit/fork.py

Pierre-Yves Chibon fac0b1
#-*- coding: utf-8 -*-
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
"""
Pierre-Yves Chibon fac0b1
 (c) 2014 - Copyright Red Hat Inc
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
 Authors:
Pierre-Yves Chibon fac0b1
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
"""
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
import flask
Pierre-Yves Chibon fac0b1
import os
Pierre-Yves Chibon fac0b1
from math import ceil
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
import pygit2
Pierre-Yves Chibon fac0b1
from sqlalchemy.exc import SQLAlchemyError
Pierre-Yves Chibon fac0b1
from pygments import highlight
Pierre-Yves Chibon fac0b1
from pygments.lexers import guess_lexer
Pierre-Yves Chibon fac0b1
from pygments.lexers.text import DiffLexer
Pierre-Yves Chibon fac0b1
from pygments.formatters import HtmlFormatter
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon 6bf4e3
import progit.doc_utils
Pierre-Yves Chibon 80bba3
import progit.lib
Pierre-Yves Chibon ac8023
import progit.forms
Pierre-Yves Chibon d5e3d0
from progit import APP, SESSION, LOG, __get_file_in_tree, cla_required
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon 47950c
def do_merge_request_pull(repo, requestid, username=None):
Pierre-Yves Chibon 47950c
    """ Merge a request pulling the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
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 not repo:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    request = progit.lib.get_pull_request(
Pierre-Yves Chibon 47950c
        SESSION, project_id=repo.id, requestid=requestid)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not request:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Pull-request not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    error_output = flask.url_for(
Pierre-Yves Chibon 47950c
        'request_pull', repo=repo.name, requestid=requestid)
Pierre-Yves Chibon 47950c
    if username:
Pierre-Yves Chibon 47950c
        error_output = flask.url_for(
Pierre-Yves Chibon 47950c
            'fork_request_pull',
Pierre-Yves Chibon 47950c
            repo=repo.name,
Pierre-Yves Chibon 47950c
            requestid=requestid,
Pierre-Yves Chibon 47950c
            username=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    # Get the fork
Pierre-Yves Chibon 47950c
    repopath = os.path.join(
Pierre-Yves Chibon 47950c
        APP.config['FORK_FOLDER'], request.repo_from.path)
Pierre-Yves Chibon 47950c
    fork_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    # Get the original repo
Pierre-Yves Chibon 47950c
    parentpath = os.path.join(APP.config['GIT_FOLDER'], request.repo.path)
Pierre-Yves Chibon 47950c
    orig_repo = pygit2.Repository(parentpath)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if orig_repo.get(request.stop_id, None):
Pierre-Yves Chibon 47950c
        flask.flash('These chanages have already been merged.', 'error')
Pierre-Yves Chibon 47950c
        # Update status
Pierre-Yves Chibon 47950c
        progit.lib.close_pull_request(SESSION, request)
Pierre-Yves Chibon 47950c
        SESSION.commit()
Pierre-Yves Chibon 47950c
        return flask.redirect(error_output)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    # Clone the original repo into a temp folder
Pierre-Yves Chibon 47950c
    newpath = tempfile.mkdtemp()
Pierre-Yves Chibon 47950c
    new_repo = pygit2.clone_repository(parentpath, newpath)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    repo_commit = fork_obj[request.stop_id]
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    ori_remote = new_repo.remotes[0]
Pierre-Yves Chibon 47950c
    # Add the fork as remote repo
Pierre-Yves Chibon 47950c
    reponame = '%s_%s' % (request.user, repo.name)
Pierre-Yves Chibon 47950c
    remote = new_repo.create_remote(reponame, repopath)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    # Fetch the commits
Pierre-Yves Chibon 47950c
    remote.fetch()
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    merge = new_repo.merge(repo_commit.oid)
Pierre-Yves Chibon 47950c
    master_ref = new_repo.lookup_reference('HEAD').resolve()
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if merge.is_fastforward:
Pierre-Yves Chibon 47950c
        master_ref.target = merge.fastforward_oid
Pierre-Yves Chibon 47950c
        refname = '%s:%s' % (master_ref.name, master_ref.name)
Pierre-Yves Chibon 47950c
        ori_remote.push(refname)
Pierre-Yves Chibon 47950c
        flask.flash('Changes merged!')
Pierre-Yves Chibon 47950c
    else:
Pierre-Yves Chibon 47950c
        flask.flash(
Pierre-Yves Chibon 47950c
            'This merge is not fast-forward and cannot be applied via '
Pierre-Yves Chibon 47950c
            'progit', 'error')
Pierre-Yves Chibon 47950c
        flask.redirect(error_output)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    # Update status
Pierre-Yves Chibon 47950c
    progit.lib.close_pull_request(SESSION, request)
Pierre-Yves Chibon 47950c
    SESSION.commit()
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.redirect(flask.url_for('view_repo', repo=repo.name))
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
def do_request_pull(repo, requestid, username=None):
Pierre-Yves Chibon 47950c
    """ Request pulling the changes from the fork into the project.
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 not repo:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    request = progit.lib.get_pull_request(
Pierre-Yves Chibon 47950c
        SESSION, project_id=repo.id, requestid=requestid)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not request:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Pull-request not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    repopath = os.path.join(
Pierre-Yves Chibon 47950c
        APP.config['FORK_FOLDER'], request.repo_from.path)
Pierre-Yves Chibon 47950c
    repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    parentname = os.path.join(
Pierre-Yves Chibon 47950c
        APP.config['GIT_FOLDER'], request.repo.path)
Pierre-Yves Chibon 47950c
    orig_repo = pygit2.Repository(parentname)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    diff_commits = []
Pierre-Yves Chibon 47950c
    diffs = []
Pierre-Yves Chibon 47950c
    repo_commit = repo_obj[request.stop_id]
Pierre-Yves Chibon 47950c
    if not repo_obj.is_empty and not orig_repo.is_empty:
Pierre-Yves Chibon 47950c
        orig_commit = orig_repo[request.start_id]
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
        for commit in repo_obj.walk(request.stop_id, pygit2.GIT_SORT_TIME):
Pierre-Yves Chibon 47950c
            if commit.oid.hex == orig_commit.oid.hex:
Pierre-Yves Chibon 47950c
                break
Pierre-Yves Chibon 47950c
            diff_commits.append(commit)
Pierre-Yves Chibon 47950c
            diffs.append(
Pierre-Yves Chibon 47950c
                repo_obj.diff(
Pierre-Yves Chibon 47950c
                    repo_obj.revparse_single(commit.parents[0].oid.hex),
Pierre-Yves Chibon 47950c
                    repo_obj.revparse_single(commit.oid.hex)
Pierre-Yves Chibon 47950c
                )
Pierre-Yves Chibon 47950c
            )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    elif orig_repo.is_empty:
Pierre-Yves Chibon 47950c
        orig_commit = None
Pierre-Yves Chibon 47950c
        diff = repo_commit.tree.diff_to_tree(swap=True)
Pierre-Yves Chibon 47950c
    else:
Pierre-Yves Chibon 47950c
        flask.flash(
Pierre-Yves Chibon 47950c
            'Fork is empty, there are no commits to request pulling',
Pierre-Yves Chibon 47950c
            'error')
Pierre-Yves Chibon 47950c
        return flask.redirect(flask.url_for(
Pierre-Yves Chibon 47950c
            'view_fork_repo', username=username, repo=repo.name))
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    html_diffs = []
Pierre-Yves Chibon 47950c
    for diff in diffs:
Pierre-Yves Chibon 47950c
        html_diffs.append(
Pierre-Yves Chibon 47950c
            highlight(
Pierre-Yves Chibon 47950c
                diff.patch,
Pierre-Yves Chibon 47950c
                DiffLexer(),
Pierre-Yves Chibon 47950c
                HtmlFormatter(
Pierre-Yves Chibon 47950c
                    noclasses=True,
Pierre-Yves Chibon 47950c
                    style="tango",)
Pierre-Yves Chibon 47950c
            )
Pierre-Yves Chibon 47950c
        )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'pull_request.html',
Pierre-Yves Chibon 47950c
        select='requests',
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username or request.user,
Pierre-Yves Chibon 47950c
        request=request,
Pierre-Yves Chibon 47950c
        repo_obj=repo_obj,
Pierre-Yves Chibon 47950c
        orig_repo=orig_repo,
Pierre-Yves Chibon 47950c
        diff_commits=diff_commits,
Pierre-Yves Chibon 47950c
        diffs=diffs,
Pierre-Yves Chibon 47950c
        html_diffs=html_diffs,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
def do_request_pulls(repo, username=None, status=True):
Pierre-Yves Chibon 47950c
    """ Returns the list of pull-requests opened on a project.
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 not repo:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if status is False or str(status).lower() == 'closed':
Pierre-Yves Chibon 47950c
        requests = progit.lib.get_pull_requests(
Pierre-Yves Chibon 47950c
            SESSION, project_id=repo.id, status=False)
Pierre-Yves Chibon 47950c
    else:
Pierre-Yves Chibon 47950c
        requests = progit.lib.get_pull_requests(
Pierre-Yves Chibon 47950c
            SESSION, project_id=repo.id, status=status)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'requests.html',
Pierre-Yves Chibon 47950c
        select='requests',
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        requests=requests,
Pierre-Yves Chibon 47950c
        status=status,
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>/request-pulls')</repo>
Pierre-Yves Chibon 47950c
def request_pulls(repo):
Pierre-Yves Chibon 47950c
    """ Request pulling the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    status = flask.request.args.get('status', True)
Pierre-Yves Chibon 47950c
    return do_request_pulls(repo, status=status)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/fork/<username>/<repo>/request-pulls')</repo></username>
Pierre-Yves Chibon 47950c
def fork_request_pulls(username, repo):
Pierre-Yves Chibon 47950c
    """ Request pulling the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    status = flask.request.args.get('status', True)
Pierre-Yves Chibon 47950c
    return do_request_pulls(repo, username=username, status=status)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/<repo>/request-pull/<requestid>')</requestid></repo>
Pierre-Yves Chibon 47950c
def request_pull(repo, requestid):
Pierre-Yves Chibon 47950c
    """ Request pulling the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_request_pull(repo, requestid)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/fork/<username>/<repo>/request-pull/<requestid>')</requestid></repo></username>
Pierre-Yves Chibon 47950c
def fork_request_pull(username, repo, requestid):
Pierre-Yves Chibon 47950c
    """ Request pulling the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_request_pull(repo, requestid, username=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/<repo>/request-pull/merge/<requestid>')</requestid></repo>
Pierre-Yves Chibon 47950c
def merge_request_pull(repo, requestid):
Pierre-Yves Chibon 47950c
    """ Request pulling the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_merge_request_pull(repo, requestid)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
@APP.route('/fork/<username>/<repo>/request-pull/merge/<requestid>')</requestid></repo></username>
Pierre-Yves Chibon 47950c
def fork_merge_request_pull(username, repo, requestid):
Pierre-Yves Chibon 47950c
    """ Request pulling the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    return do_merge_request_pull(repo, requestid, username=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
## Specific actions
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon e03e84
@APP.route('/do_fork/<repo>')</repo>
Pierre-Yves Chibon e03e84
@APP.route('/do_fork/<username>/<repo>')</repo></username>
Pierre-Yves Chibon d5e3d0
@cla_required
Pierre-Yves Chibon 20ccbb
def fork_project(repo, username=None):
Pierre-Yves Chibon fac0b1
    """ Fork the project specified into the user's namespace
Pierre-Yves Chibon fac0b1
    """
Pierre-Yves Chibon 20ccbb
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 80bba3
Pierre-Yves Chibon 80bba3
    if repo is None:
Pierre-Yves Chibon fac0b1
        flask.abort(404)
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon 80bba3
    try:
Pierre-Yves Chibon 80bba3
        message = progit.lib.fork_project(
Pierre-Yves Chibon 80bba3
            session=SESSION,
Pierre-Yves Chibon 80bba3
            repo=repo,
Pierre-Yves Chibon 6160b6
            repofolder=APP.config['GIT_FOLDER'],
Pierre-Yves Chibon 6160b6
            forkfolder=APP.config['FORK_FOLDER'],
Pierre-Yves Chibon 6160b6
            docfolder=APP.config['WIKI_FOLDER'],
Pierre-Yves Chibon 80bba3
            user=flask.g.fas_user.username)
Pierre-Yves Chibon 80bba3
Pierre-Yves Chibon 80bba3
        SESSION.commit()
Pierre-Yves Chibon 80bba3
        flask.flash(message)
Pierre-Yves Chibon 80bba3
        return flask.redirect(
Pierre-Yves Chibon 792a86
            flask.url_for(
Pierre-Yves Chibon 792a86
                'view_fork_repo',
Pierre-Yves Chibon 792a86
                username=flask.g.fas_user.username,
Pierre-Yves Chibon 792a86
                repo=repo.name)
Pierre-Yves Chibon 80bba3
        )
Pierre-Yves Chibon 80bba3
    except progit.exceptions.ProgitException, err:
Pierre-Yves Chibon 80bba3
        flask.flash(str(err), 'error')
Pierre-Yves Chibon 80bba3
    except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon 80bba3
        SESSION.rollback()
Pierre-Yves Chibon 80bba3
        flask.flash(str(err), 'error')
Pierre-Yves Chibon 80bba3
Pierre-Yves Chibon 792a86
    return flask.redirect(flask.url_for('view_repo', repo=repo.name))
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon ac8023
@APP.route('/fork/<username>/<repo>/request-pull/new',</repo></username>
Pierre-Yves Chibon 3bb858
           methods=('GET', 'POST'))
Pierre-Yves Chibon ac8023
@APP.route('/fork/<username>/<repo>/request-pull/new/<commitid>',</commitid></repo></username>
Pierre-Yves Chibon ac8023
           methods=('GET', 'POST'))
Pierre-Yves Chibon d5e3d0
@cla_required
Pierre-Yves Chibon ac8023
def new_request_pull(username, repo, commitid=None):
Pierre-Yves Chibon 82055c
    """ Request pulling the changes from the fork into the project.
Pierre-Yves Chibon 82055c
    """
Pierre-Yves Chibon 82055c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 82055c
    if not repo:
Pierre-Yves Chibon 82055c
        flask.abort(404)
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon ebf29e
    repopath = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 85755c
    repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 82055c
    parentname = os.path.join(APP.config['GIT_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 82055c
    orig_repo = pygit2.Repository(parentname)
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 82055c
    if commitid is None:
Pierre-Yves Chibon 82055c
        commitid = repo_obj.head.target
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 82055c
    diff_commits = []
Pierre-Yves Chibon 82055c
    diffs = []
Pierre-Yves Chibon 82055c
    if not repo_obj.is_empty and not orig_repo.is_empty:
Pierre-Yves Chibon 82055c
        orig_commit = orig_repo[orig_repo.head.target]
Pierre-Yves Chibon 82055c
        repo_commit = repo_obj[commitid]
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 82055c
        for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_TIME):
Pierre-Yves Chibon 82055c
            if commit.oid.hex == orig_commit.oid.hex:
Pierre-Yves Chibon 82055c
                break
Pierre-Yves Chibon 82055c
            diff_commits.append(commit)
Pierre-Yves Chibon 82055c
            diffs.append(
Pierre-Yves Chibon 82055c
                repo_obj.diff(
Pierre-Yves Chibon 82055c
                    repo_obj.revparse_single(commit.parents[0].oid.hex),
Pierre-Yves Chibon 82055c
                    repo_obj.revparse_single(commit.oid.hex)
Pierre-Yves Chibon 82055c
                )
Pierre-Yves Chibon 82055c
            )
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 82055c
    elif orig_repo.is_empty:
Pierre-Yves Chibon ac8023
        orig_commit = None
Pierre-Yves Chibon 85755c
        repo_commit = repo_obj[repo_obj.head.target]
Pierre-Yves Chibon 85755c
        diff = repo_commit.tree.diff_to_tree(swap=True)
Pierre-Yves Chibon 82055c
    else:
Pierre-Yves Chibon 82055c
        flask.flash(
Pierre-Yves Chibon 82055c
            'Fork is empty, there are no commits to request pulling',
Pierre-Yves Chibon 82055c
            'error')
Pierre-Yves Chibon 82055c
        return flask.redirect(flask.url_for(
Pierre-Yves Chibon 82055c
            'view_fork_repo', username=username, repo=repo.name))
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 82055c
    html_diffs = []
Pierre-Yves Chibon 82055c
    for diff in diffs:
Pierre-Yves Chibon 82055c
        html_diffs.append(
Pierre-Yves Chibon 82055c
            highlight(
Pierre-Yves Chibon 82055c
                diff.patch,
Pierre-Yves Chibon 82055c
                DiffLexer(),
Pierre-Yves Chibon 82055c
                HtmlFormatter(
Pierre-Yves Chibon 82055c
                    noclasses=True,
Pierre-Yves Chibon 82055c
                    style="tango",)
Pierre-Yves Chibon 82055c
            )
Pierre-Yves Chibon 82055c
        )
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon ac8023
    form = progit.forms.RequestPullForm()
Pierre-Yves Chibon ac8023
    if form.validate_on_submit():
Pierre-Yves Chibon ac8023
        try:
Pierre-Yves Chibon ac8023
            if orig_commit:
Pierre-Yves Chibon ac8023
                orig_commit = orig_commit.oid.hex
Pierre-Yves Chibon ac8023
            message = progit.lib.new_pull_request(
Pierre-Yves Chibon ac8023
                SESSION,
Pierre-Yves Chibon ac8023
                repo=repo.parent,
Pierre-Yves Chibon ac8023
                repo_from=repo,
Pierre-Yves Chibon ac8023
                title=form.title.data,
Pierre-Yves Chibon ac8023
                start_id=orig_commit,
Pierre-Yves Chibon ac8023
                stop_id=repo_commit.oid.hex,
Pierre-Yves Chibon ac8023
                user=flask.g.fas_user.username,
Pierre-Yves Chibon ac8023
            )
Pierre-Yves Chibon ac8023
            SESSION.commit()
Pierre-Yves Chibon ac8023
            flask.flash(message)
Pierre-Yves Chibon ac8023
            return flask.redirect(flask.url_for(
Pierre-Yves Chibon ac8023
                'view_fork_issues', username=username, repo=repo.name))
Pierre-Yves Chibon ac8023
        except progit.exceptions.ProgitException, err:
Pierre-Yves Chibon ac8023
            flask.flash(str(err), 'error')
Pierre-Yves Chibon ac8023
        except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon ac8023
            SESSION.rollback()
Pierre-Yves Chibon ac8023
            flask.flash(str(err), 'error')
Pierre-Yves Chibon ac8023
Pierre-Yves Chibon 82055c
    return flask.render_template(
Pierre-Yves Chibon 82055c
        'pull_request.html',
Pierre-Yves Chibon 82055c
        repo=repo,
Pierre-Yves Chibon 82055c
        username=username,
Pierre-Yves Chibon ac8023
        commitid=commitid,
Pierre-Yves Chibon 82055c
        repo_obj=repo_obj,
Pierre-Yves Chibon 82055c
        orig_repo=orig_repo,
Pierre-Yves Chibon 82055c
        diff_commits=diff_commits,
Pierre-Yves Chibon 82055c
        diffs=diffs,
Pierre-Yves Chibon 82055c
        html_diffs=html_diffs,
Pierre-Yves Chibon ac8023
        form=form,
Pierre-Yves Chibon 82055c
    )