Blame pagure/ui/fork.py

Pierre-Yves Chibon 33b534
# -*- coding: utf-8 -*-
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
"""
Pierre-Yves Chibon 0c0047
 (c) 2014-2017 - 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 22a554
# pylint: disable=too-many-return-statements
Pierre-Yves Chibon 22a554
# pylint: disable=too-many-branches
Pierre-Yves Chibon 22a554
# pylint: disable=too-many-arguments
Pierre-Yves Chibon 22a554
# pylint: disable=too-many-locals
Pierre-Yves Chibon 22a554
# pylint: disable=too-many-statements
Pierre-Yves Chibon 22a554
# pylint: disable=too-many-lines
Pierre-Yves Chibon 22a554
Pierre-Yves Chibon 11d3da
Pierre-Yves Chibon 67d1cc
from __future__ import unicode_literals, absolute_import
Aurélien Bompard dcf6f6
Pierre-Yves Chibon 4635b5
import logging
Pierre-Yves Chibon fac0b1
import os
Pierre-Yves Chibon 3f299a
from math import ceil
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon 4635b5
import flask
Pierre-Yves Chibon fac0b1
import pygit2
Pierre-Yves Chibon fac0b1
from sqlalchemy.exc import SQLAlchemyError
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon dbf3e1
import pagure
Pierre-Yves Chibon fe5017
import pagure.doc_utils
Pierre-Yves Chibon dbf3e1
import pagure.exceptions
Pierre-Yves Chibon fe5017
import pagure.lib.git
Slavek Kabrda a80d7c
import pagure.lib.plugins
Pierre-Yves Chibon 930073
import pagure.lib.query
Patrick Uiterwijk c0c627
import pagure.lib.tasks
Pierre-Yves Chibon fe5017
import pagure.forms
Pierre-Yves Chibon b130e5
from pagure.config import config as pagure_config
Pierre-Yves Chibon b130e5
from pagure.ui import UI_NS
Pierre-Yves Chibon 78ba11
from pagure.utils import (
Pierre-Yves Chibon 9c2953
    login_required,
Pierre-Yves Chibon 9c2953
    __get_file_in_tree,
Pierre-Yves Chibon 9c2953
    get_parent_repo_path,
Pierre-Yves Chibon 9c2953
    is_true,
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon 4635b5
_log = logging.getLogger(__name__)
Pierre-Yves Chibon 4635b5
Pierre-Yves Chibon 4635b5
Pierre-Yves Chibon 87633f
def _get_parent_request_repo_path(repo):
Pierre-Yves Chibon 87633f
    """ Return the path of the parent git repository corresponding to the
Pierre-Yves Chibon 87633f
    provided Repository object from the DB.
Pierre-Yves Chibon 87633f
    """
Pierre-Yves Chibon 87633f
    if repo.parent:
Patrick Uiterwijk 3f97f6
        return repo.parent.repopath("requests")
Pierre-Yves Chibon 87633f
    else:
Patrick Uiterwijk 3f97f6
        return repo.repopath("requests")
Pierre-Yves Chibon 87633f
Pierre-Yves Chibon 87633f
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-requests/")</repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-requests")</repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<namespace>/<repo>/pull-requests/")</repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<namespace>/<repo>/pull-requests")</repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<repo>/pull-requests/")</repo></username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<repo>/pull-requests")</repo></username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<namespace>/<repo>/pull-requests/")</repo></namespace></username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<namespace>/<repo>/pull-requests")</repo></namespace></username>
Pierre-Yves Chibon 4501da
def request_pulls(repo, username=None, namespace=None):
ymdatta 9ab5d0
    """ List all Pull-requests associated to a repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 9c2953
    status = flask.request.args.get("status", "Open")
Pierre-Yves Chibon 9c2953
    assignee = flask.request.args.get("assignee", None)
Pierre-Yves Chibon 9c2953
    search_pattern = flask.request.args.get("search_pattern", None)
Pierre-Yves Chibon 9c2953
    author = flask.request.args.get("author", None)
Pierre-Yves Chibon 9c2953
    order = flask.request.args.get("order", "desc")
Pierre-Yves Chibon 9c2953
    order_key = flask.request.args.get("order_key", "date_created")
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-requests found for this project")
Pierre-Yves Chibon 3c6562
Pierre-Yves Chibon 930073
    total_open = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, status=True, count=True
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 81c3a2
Pierre-Yves Chibon 930073
    total_merged = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, status="Merged", count=True
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 81c3a2
Pierre-Yves Chibon 9c2953
    if status.lower() == "merged" or is_true(status, ["false", "0"]):
Pierre-Yves Chibon 9c2953
        status_filter = "Merged"
Pierre-Yves Chibon 930073
        requests = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon b130e5
            flask.g.session,
Pierre-Yves Chibon 58a877
            project_id=repo.id,
Pierre-Yves Chibon 9c2953
            status="Merged",
ymdatta 9ab5d0
            order=order,
ymdatta 9ab5d0
            order_key=order_key,
Pierre-Yves Chibon 58a877
            assignee=assignee,
Pierre-Yves Chibon 3f299a
            author=author,
Ryan Lerch 4ff673
            search_pattern=search_pattern,
Pierre-Yves Chibon 3f299a
            offset=flask.g.offset,
Pierre-Yves Chibon 9c2953
            limit=flask.g.limit,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    elif is_true(status, ["true", "1", "open"]):
Pierre-Yves Chibon 9c2953
        status_filter = "Open"
Pierre-Yves Chibon 930073
        requests = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon b130e5
            flask.g.session,
Pierre-Yves Chibon 3f299a
            project_id=repo.id,
Pierre-Yves Chibon 9c2953
            status="Open",
Ryan Lerch 81c3a2
            order=order,
Ryan Lerch 81c3a2
            order_key=order_key,
Pierre-Yves Chibon 3f299a
            assignee=assignee,
Pierre-Yves Chibon 3f299a
            author=author,
Ryan Lerch 4ff673
            search_pattern=search_pattern,
Ryan Lerch 81c3a2
            offset=flask.g.offset,
Pierre-Yves Chibon 9c2953
            limit=flask.g.limit,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    elif status.lower() == "closed":
Pierre-Yves Chibon 9c2953
        status_filter = "Closed"
Pierre-Yves Chibon 930073
        requests = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon b130e5
            flask.g.session,
Pierre-Yves Chibon 58a877
            project_id=repo.id,
Pierre-Yves Chibon 9c2953
            status="Closed",
Ryan Lerch 81c3a2
            order=order,
Ryan Lerch 81c3a2
            order_key=order_key,
Pierre-Yves Chibon 58a877
            assignee=assignee,
Pierre-Yves Chibon 58a877
            author=author,
Ryan Lerch 4ff673
            search_pattern=search_pattern,
Ryan Lerch 81c3a2
            offset=flask.g.offset,
Pierre-Yves Chibon 9c2953
            limit=flask.g.limit,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 47950c
    else:
Ryan Lerch 81c3a2
        status_filter = None
Pierre-Yves Chibon 930073
        requests = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon b130e5
            flask.g.session,
Pierre-Yves Chibon 58a877
            project_id=repo.id,
Ryan Lerch 81c3a2
            status=None,
ymdatta 9ab5d0
            order=order,
ymdatta 9ab5d0
            order_key=order_key,
Pierre-Yves Chibon 58a877
            assignee=assignee,
Pierre-Yves Chibon 58a877
            author=author,
Ryan Lerch 4ff673
            search_pattern=search_pattern,
Pierre-Yves Chibon 3f299a
            offset=flask.g.offset,
Pierre-Yves Chibon 9c2953
            limit=flask.g.limit,
Pierre-Yves Chibon 9c2953
        )
Ryan Lerch 81c3a2
Pierre-Yves Chibon 930073
    open_cnt = pagure.lib.query.search_pull_requests(
Ryan Lerch 81c3a2
        flask.g.session,
Ryan Lerch 81c3a2
        project_id=repo.id,
Pierre-Yves Chibon 9c2953
        status="Open",
Ryan Lerch 81c3a2
        assignee=assignee,
Ryan Lerch 81c3a2
        author=author,
Ryan Lerch 4ff673
        search_pattern=search_pattern,
Pierre-Yves Chibon 9c2953
        count=True,
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 81c3a2
Pierre-Yves Chibon 930073
    merged_cnt = pagure.lib.query.search_pull_requests(
Ryan Lerch 81c3a2
        flask.g.session,
Ryan Lerch 81c3a2
        project_id=repo.id,
Pierre-Yves Chibon 9c2953
        status="Merged",
Ryan Lerch 81c3a2
        assignee=assignee,
Ryan Lerch 81c3a2
        author=author,
Ryan Lerch 4ff673
        search_pattern=search_pattern,
Pierre-Yves Chibon 9c2953
        count=True,
Pierre-Yves Chibon 9c2953
    )
Ryan Lerch 81c3a2
Pierre-Yves Chibon 930073
    closed_cnt = pagure.lib.query.search_pull_requests(
Ryan Lerch 81c3a2
        flask.g.session,
Ryan Lerch 81c3a2
        project_id=repo.id,
Pierre-Yves Chibon 9c2953
        status="Closed",
Ryan Lerch 81c3a2
        assignee=assignee,
Ryan Lerch 81c3a2
        author=author,
Ryan Lerch 4ff673
        search_pattern=search_pattern,
Pierre-Yves Chibon 9c2953
        count=True,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon bcd7a0
    repo_obj = flask.g.repo_obj
Pierre-Yves Chibon 7224d4
    if not repo_obj.is_empty and not repo_obj.head_is_unborn:
Pierre-Yves Chibon 7224d4
        head = repo_obj.head.shorthand
Pierre-Yves Chibon 7224d4
    else:
Pierre-Yves Chibon 9c2953
        head = "master"
Pierre-Yves Chibon 7224d4
Pierre-Yves Chibon 0c0047
    total_page = 1
Ryan Lerch 81c3a2
    if len(requests):
Pierre-Yves Chibon 9c2953
        if status_filter == "Closed":
Pierre-Yves Chibon cd4d49
            total_requests = closed_cnt
Pierre-Yves Chibon 9c2953
        elif status_filter == "Merged":
Pierre-Yves Chibon cd4d49
            total_requests = merged_cnt
Pierre-Yves Chibon 9c2953
        elif status_filter == "Open":
Pierre-Yves Chibon cd4d49
            total_requests = open_cnt
Pierre-Yves Chibon cd4d49
        else:
Pierre-Yves Chibon cd4d49
            total_requests = closed_cnt + merged_cnt + open_cnt
Pierre-Yves Chibon cd4d49
        total_page = int(ceil(total_requests / float(flask.g.limit)))
Pierre-Yves Chibon 3f299a
Pierre-Yves Chibon b31474
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "requests.html",
Pierre-Yves Chibon 9c2953
        select="requests",
Pierre-Yves Chibon b31474
        repo=repo,
Pierre-Yves Chibon b31474
        username=username,
Pierre-Yves Chibon b31474
        requests=requests,
Ryan Lerch 81c3a2
        open_cnt=open_cnt,
Ryan Lerch 81c3a2
        merged_cnt=merged_cnt,
Ryan Lerch 81c3a2
        closed_cnt=closed_cnt,
ymdatta 9ab5d0
        order=order,
ymdatta 9ab5d0
        order_key=order_key,
Pierre-Yves Chibon b31474
        status=status,
Ryan Lerch 81c3a2
        status_filter=status_filter,
Pierre-Yves Chibon 58a877
        assignee=assignee,
Pierre-Yves Chibon 58a877
        author=author,
Ryan Lerch 4ff673
        search_pattern=search_pattern,
Pierre-Yves Chibon 7224d4
        head=head,
Pierre-Yves Chibon 3f299a
        total_page=total_page,
Ryan Lerch 81c3a2
        total_open=total_open,
Ryan Lerch 81c3a2
        total_merged=total_merged,
Pierre-Yves Chibon b31474
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/<int:requestid>/")</int:requestid></repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/<int:requestid>")</int:requestid></repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<namespace>/<repo>/pull-request/<int:requestid>/")</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<namespace>/<repo>/pull-request/<int:requestid>")</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<repo>/pull-request/<int:requestid>/")</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<repo>/pull-request/<int:requestid>")</int:requestid></repo></username>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/"</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>"</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon 4501da
def request_pull(repo, requestid, username=None, namespace=None):
Stanislav Laznicka 14c8c3
    """ Create a pull request with the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 9c2953
    _log.info("Viewing pull Request #%s repo: %s", requestid, repo.fullname)
Pierre-Yves Chibon e4c63c
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-requests found for this project")
Pierre-Yves Chibon 3c6562
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 24e217
    if request.remote:
Pierre-Yves Chibon b130e5
        repopath = pagure.utils.get_remote_repo_path(
Pierre-Yves Chibon 9c2953
            request.remote_git, request.branch_from
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon b130e5
        parentpath = pagure.utils.get_repo_path(request.project)
Pierre-Yves Chibon 24e217
    else:
Pierre-Yves Chibon 24e217
        repo_from = request.project_from
Pierre-Yves Chibon b130e5
        parentpath = pagure.utils.get_repo_path(request.project)
Pierre-Yves Chibon 5da9ba
        repopath = parentpath
Pierre-Yves Chibon ff9832
        if repo_from:
Pierre-Yves Chibon b130e5
            repopath = pagure.utils.get_repo_path(repo_from)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 24e217
    repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon 8df273
    orig_repo = pygit2.Repository(parentpath)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon f96fb7
    diff_commits = []
Pierre-Yves Chibon f96fb7
    diff = None
Pierre-Yves Chibon e933e6
    # Closed pull-request
Pierre-Yves Chibon 9c2953
    if request.status != "Open":
Pierre-Yves Chibon e933e6
        commitid = request.commit_stop
Pierre-Yves Chibon 99d0d4
        try:
Slavek Kabrda 0dd0cd
            for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_NONE):
Pierre-Yves Chibon 99d0d4
                diff_commits.append(commit)
Pierre-Yves Chibon 99d0d4
                if commit.oid.hex == request.commit_start:
Pierre-Yves Chibon 99d0d4
                    break
Pierre-Yves Chibon 99d0d4
        except KeyError:
Pierre-Yves Chibon 99d0d4
            # This happens when repo.walk() cannot find commitid
Pierre-Yves Chibon 99d0d4
            pass
Pierre-Yves Chibon c1e934
Pierre-Yves Chibon d1a014
        if diff_commits:
Pierre-Yves Chibon 83bb93
            # Ensure the first commit in the PR as a parent, otherwise
Pierre-Yves Chibon 83bb93
            # point to it
Pierre-Yves Chibon 83bb93
            start = diff_commits[-1].oid.hex
Pierre-Yves Chibon 83bb93
            if diff_commits[-1].parents:
Pierre-Yves Chibon 83bb93
                start = diff_commits[-1].parents[0].oid.hex
Pierre-Yves Chibon 83bb93
Pierre-Yves Chibon 83bb93
            # If the start and the end commits are the same, it means we are,
Pierre-Yves Chibon 83bb93
            # dealing with one commit that has no parent, so just diff that
Pierre-Yves Chibon 83bb93
            # one commit
Pierre-Yves Chibon 83bb93
            if start == diff_commits[0].oid.hex:
Pierre-Yves Chibon 83bb93
                diff = diff_commits[0].tree.diff_to_tree(swap=True)
Pierre-Yves Chibon 83bb93
            else:
Pierre-Yves Chibon 83bb93
                diff = repo_obj.diff(
Pierre-Yves Chibon 83bb93
                    repo_obj.revparse_single(start),
Pierre-Yves Chibon 9c2953
                    repo_obj.revparse_single(diff_commits[0].oid.hex),
Pierre-Yves Chibon 83bb93
                )
Pierre-Yves Chibon e933e6
    else:
Pierre-Yves Chibon dbf3e1
        try:
Pierre-Yves Chibon dbf3e1
            diff_commits, diff = pagure.lib.git.diff_pull_request(
Patrick Uiterwijk 3f97f6
                flask.g.session, request, repo_obj, orig_repo
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon dbf3e1
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
            flask.flash("%s" % err, "error")
Pierre-Yves Chibon dbf3e1
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon dbf3e1
            flask.flash(
Pierre-Yves Chibon 9c2953
                "Could not update this pull-request in the database", "error"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 54164e
    if diff:
Pierre-Yves Chibon 54164e
        diff.find_similar()
Pierre-Yves Chibon d5c8ac
Lubomír Sedlář 7c6b11
    form = pagure.forms.MergePRForm()
Slavek Kabrda a80d7c
    trigger_ci_pr_form = pagure.forms.TriggerCIPRForm()
Slavek Kabrda a80d7c
Slavek Kabrda a80d7c
    # we need to leave out all members of trigger_ci_conf that have
Slavek Kabrda a80d7c
    # "meta" set to False or meta["requires_project_hook_attr"] condition
Slavek Kabrda a80d7c
    # defined and it's not met
Slavek Kabrda a80d7c
    trigger_ci_conf = pagure_config["TRIGGER_CI"]
Slavek Kabrda a80d7c
    if not isinstance(trigger_ci_conf, dict):
Slavek Kabrda a80d7c
        trigger_ci_conf = {}
Slavek Kabrda a80d7c
    trigger_ci = {}
Slavek Kabrda a80d7c
    # make sure all the backrefs are set properly on repo
Slavek Kabrda a80d7c
    pagure.lib.plugins.get_enabled_plugins(repo)
Slavek Kabrda a80d7c
    for comment, meta in trigger_ci_conf.items():
Slavek Kabrda a80d7c
        if not meta:
Slavek Kabrda a80d7c
            continue
Slavek Kabrda a80d7c
        cond = meta.get("requires_project_hook_attr", ())
Slavek Kabrda a80d7c
        if cond and not pagure.utils.project_has_hook_attr_value(repo, *cond):
Slavek Kabrda a80d7c
            continue
Slavek Kabrda a80d7c
        trigger_ci[comment] = meta
Johan Cwiklinski fd18bd
Lubomír Sedlář ed7075
    can_delete_branch = (
Pierre-Yves Chibon 9c2953
        pagure_config.get("ALLOW_DELETE_BRANCH", True)
Lubomír Sedlář ed7075
        and not request.remote_git
Julen Landa Alustiza 38a4ae
        and request.project_from
Lubomír Sedlář ed7075
        and pagure.utils.is_repo_committer(request.project_from)
Lubomír Sedlář ed7075
    )
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "repo_pull_request.html",
Pierre-Yves Chibon 9c2953
        select="requests",
Pierre-Yves Chibon 04ed02
        requestid=requestid,
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 41558c
        username=username,
Pierre-Yves Chibon 200ea3
        repo_obj=repo_obj,
Pierre-Yves Chibon 87ba70
        pull_request=request,
Pierre-Yves Chibon 47950c
        diff_commits=diff_commits,
Pierre-Yves Chibon e31131
        diff=diff,
Johan Cwiklinski fd18bd
        mergeform=form,
Pierre-Yves Chibon 930073
        subscribers=pagure.lib.query.get_watch_list(flask.g.session, request),
Pierre-Yves Chibon 930073
        tag_list=pagure.lib.query.get_tags_of_project(flask.g.session, repo),
Lubomír Sedlář ed7075
        can_delete_branch=can_delete_branch,
Slavek Kabrda a80d7c
        trigger_ci=trigger_ci,
Slavek Kabrda a80d7c
        trigger_ci_pr_form=trigger_ci_pr_form,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon e31131
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/<int:requestid>.patch")</int:requestid></repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<namespace>/<repo>/pull-request/<int:requestid>.patch")</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<repo>/pull-request/<int:requestid>.patch")</int:requestid></repo></username>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>.patch"</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon 4501da
def request_pull_patch(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon e7de33
    """ Returns the commits from the specified pull-request as patches.
Pierre-Yves Chibon e7de33
    """
Pierre-Yves Chibon d9d369
    return request_pull_to_diff_or_patch(
Pierre-Yves Chibon 9c2953
        repo, requestid, username, namespace, diff=False
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon d9d369
Pierre-Yves Chibon d9d369
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/<int:requestid>.diff")</int:requestid></repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<namespace>/<repo>/pull-request/<int:requestid>.diff")</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<repo>/pull-request/<int:requestid>.diff")</int:requestid></repo></username>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>.diff"</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon d9d369
def request_pull_diff(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon d9d369
    """ Returns the commits from the specified pull-request as patches.
Pierre-Yves Chibon d9d369
    """
Pierre-Yves Chibon d9d369
    return request_pull_to_diff_or_patch(
Pierre-Yves Chibon 9c2953
        repo, requestid, username, namespace, diff=True
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon d9d369
Pierre-Yves Chibon d9d369
Pierre-Yves Chibon d9d369
def request_pull_to_diff_or_patch(
Pierre-Yves Chibon 9c2953
    repo, requestid, username=None, namespace=None, diff=False
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon d9d369
    """ Returns the commits from the specified pull-request as patches.
Pierre-Yves Chibon 7f7053
Pierre-Yves Chibon 7f7053
    :arg repo: the `pagure.lib.model.Project` object of the current pagure
Pierre-Yves Chibon 7f7053
        project browsed
Pierre-Yves Chibon 7f7053
    :type repo: `pagure.lib.model.Project`
Pierre-Yves Chibon 7f7053
    :arg requestid: the identifier of the pull-request to convert to patch
Pierre-Yves Chibon 7f7053
        or diff
Pierre-Yves Chibon 7f7053
    :type requestid: int
Pierre-Yves Chibon 7f7053
    :kwarg username: the username of the user who forked then project when
Pierre-Yves Chibon 7f7053
        the project viewed is a fork
Pierre-Yves Chibon 7f7053
    :type username: str or None
Pierre-Yves Chibon 7f7053
    :kwarg namespace: the namespace of the project if it has one
Pierre-Yves Chibon 7f7053
    :type namespace: str or None
Pierre-Yves Chibon 7f7053
    :kwarg diff: a boolean whether the data returned is a patch or a diff
Pierre-Yves Chibon 7f7053
    :type diff: boolean
Pierre-Yves Chibon 7f7053
    :return: the patch or diff representation of the specified pull-request
Pierre-Yves Chibon 7f7053
    :rtype: str
Pierre-Yves Chibon 7f7053
Pierre-Yves Chibon d9d369
    """
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon e7de33
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-requests found for this project")
Pierre-Yves Chibon 3c6562
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon e7de33
Pierre-Yves Chibon e7de33
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
Pierre-Yves Chibon e7de33
Pierre-Yves Chibon 1d4c5f
    if request.remote:
Pierre-Yves Chibon b9d537
        repopath = pagure.utils.get_remote_repo_path(
Pierre-Yves Chibon 9c2953
            request.remote_git, request.branch_from
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon b130e5
        parentpath = pagure.utils.get_repo_path(request.project)
Pierre-Yves Chibon 1d4c5f
    else:
Pierre-Yves Chibon 1d4c5f
        repo_from = request.project_from
Pierre-Yves Chibon 5da9ba
        parentpath = pagure.utils.get_repo_path(request.project)
Pierre-Yves Chibon 5da9ba
        repopath = parentpath
Pierre-Yves Chibon 5da9ba
        if repo_from:
Pierre-Yves Chibon 5da9ba
            repopath = pagure.utils.get_repo_path(repo_from)
Pierre-Yves Chibon e7de33
Pierre-Yves Chibon 1d4c5f
    repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon 8df273
    orig_repo = pygit2.Repository(parentpath)
Pierre-Yves Chibon e7de33
Pierre-Yves Chibon 18e007
    branch = repo_obj.lookup_branch(request.branch_from)
Pierre-Yves Chibon 9dede1
    commitid = None
Pierre-Yves Chibon 9dede1
    if branch:
Pierre-Yves Chibon 29ff0a
        commitid = branch.peel().hex
Pierre-Yves Chibon 18e007
Pierre-Yves Chibon e7de33
    diff_commits = []
Pierre-Yves Chibon 9c2953
    if request.status != "Open":
Pierre-Yves Chibon a8e3e5
        commitid = request.commit_stop
Pierre-Yves Chibon 06f078
        try:
Slavek Kabrda 0dd0cd
            for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_NONE):
Pierre-Yves Chibon 06f078
                diff_commits.append(commit)
Pierre-Yves Chibon 06f078
                if commit.oid.hex == request.commit_start:
Pierre-Yves Chibon 06f078
                    break
Pierre-Yves Chibon 06f078
        except KeyError:
Pierre-Yves Chibon 06f078
            # This happens when repo.walk() cannot find commitid
Pierre-Yves Chibon 06f078
            pass
Pierre-Yves Chibon e7de33
    else:
Pierre-Yves Chibon a8e3e5
        try:
Pierre-Yves Chibon 164a57
            diff_commits = pagure.lib.git.diff_pull_request(
Patrick Uiterwijk 3f97f6
                flask.g.session, request, repo_obj, orig_repo, with_diff=False
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon a8e3e5
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
            flask.flash("%s" % err, "error")
Pierre-Yves Chibon 9c2953
            return flask.redirect(
Pierre-Yves Chibon 9c2953
                flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
                    username=username,
Pierre-Yves Chibon 9c2953
                    repo=repo.name,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon a8e3e5
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon a8e3e5
            flask.flash(
Pierre-Yves Chibon 9c2953
                "Could not update this pull-request in the database", "error"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon e7de33
Pierre-Yves Chibon e7de33
    diff_commits.reverse()
Pierre-Yves Chibon 4b90cc
    patch = pagure.lib.git.commit_to_patch(
Pierre-Yves Chibon 9c2953
        repo_obj, diff_commits, diff_view=diff
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon e7de33
Pierre-Yves Chibon e7de33
    return flask.Response(patch, content_type="text/plain;charset=UTF-8")
Pierre-Yves Chibon e7de33
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<repo>/pull-request/<int:requestid>/edit/", methods=("GET", "POST")</int:requestid></repo>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<repo>/pull-request/<int:requestid>/edit", methods=("GET", "POST")</int:requestid></repo>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/edit/",</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/edit",</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/edit/",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/edit",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/edit/",</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/edit",</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 4501da
def request_pull_edit(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon b19872
    """ Edit the title of a pull-request.
Pierre-Yves Chibon b19872
    """
Pierre-Yves Chibon b19872
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon b19872
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-requests found for this project")
Pierre-Yves Chibon b19872
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon b19872
Pierre-Yves Chibon b19872
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
Pierre-Yves Chibon b19872
Pierre-Yves Chibon 9c2953
    if request.status != "Open":
Pierre-Yves Chibon c6cc5c
        flask.abort(400, description="Pull-request is already closed")
Pierre-Yves Chibon 3296f0
Pierre-Yves Chibon 9c2953
    if (
Pierre-Yves Chibon 9c2953
        not flask.g.repo_committer
Pierre-Yves Chibon 9c2953
        and flask.g.fas_user.username != request.user.username
Pierre-Yves Chibon 9c2953
    ):
Pierre-Yves Chibon c6cc5c
        flask.abort(
Pierre-Yves Chibon c6cc5c
            403, description="You are not allowed to edit this pull-request"
Pierre-Yves Chibon c6cc5c
        )
Pierre-Yves Chibon b19872
Pierre-Yves Chibon b19872
    form = pagure.forms.RequestPullForm()
Pierre-Yves Chibon b19872
    if form.validate_on_submit():
Pierre-Yves Chibon 53e651
        request.title = form.title.data.strip()
Pierre-Yves Chibon 53e651
        request.initial_comment = form.initial_comment.data.strip()
Pierre-Yves Chibon b130e5
        flask.g.session.add(request)
Pierre-Yves Chibon 053ab1
        if not request.private and not request.project.private:
Pierre-Yves Chibon 053ab1
            pagure.lib.notify.log(
Pierre-Yves Chibon 053ab1
                request.project,
Pierre-Yves Chibon 053ab1
                topic="pull-request.initial_comment.edited",
Pierre-Yves Chibon 053ab1
                msg={
Pierre-Yves Chibon 053ab1
                    "pullrequest": request.to_json(
Pierre-Yves Chibon 053ab1
                        public=True, with_comments=False
Pierre-Yves Chibon 053ab1
                    ),
Pierre-Yves Chibon 053ab1
                    "project": request.project.to_json(public=True),
Pierre-Yves Chibon 053ab1
                    "agent": flask.g.fas_user.username,
Pierre-Yves Chibon 053ab1
                },
Pierre-Yves Chibon 053ab1
            )
Pierre-Yves Chibon b19872
        try:
Pierre-Yves Chibon 2479ca
            # Link the PR to issue(s) if there is such link
Pierre-Yves Chibon 2479ca
            pagure.lib.query.link_pr_to_issue_on_description(
Pierre-Yves Chibon 2479ca
                flask.g.session, request
Pierre-Yves Chibon 2479ca
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 9c2953
            flask.flash("Pull request edited!")
Pierre-Yves Chibon b19872
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon b19872
            flask.flash(
Pierre-Yves Chibon 9c2953
                "Could not edit this pull-request in the database", "error"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    elif flask.request.method == "GET":
Pierre-Yves Chibon b19872
        form.title.data = request.title
Pierre-Yves Chibon 53e651
        form.initial_comment.data = request.initial_comment
Pierre-Yves Chibon b19872
Pierre-Yves Chibon b19872
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "pull_request_title.html",
Pierre-Yves Chibon 9c2953
        select="requests",
Pierre-Yves Chibon b19872
        request=request,
Pierre-Yves Chibon b19872
        repo=repo,
Pierre-Yves Chibon b19872
        username=username,
Pierre-Yves Chibon b19872
        form=form,
Pierre-Yves Chibon b19872
    )
Pierre-Yves Chibon b19872
Pierre-Yves Chibon b19872
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/<int:requestid>/comment", methods=["POST"])</int:requestid></repo>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<repo>/pull-request/<int:requestid>/comment/<commit>/"</commit></int:requestid></repo>
Pierre-Yves Chibon 9c2953
    "<path:filename>/<row>",</row></path:filename>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/comment",</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/comment/<commit>/"</commit></int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
    "<path:filename>/<row>",</row></path:filename>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/comment",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/comment/"</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    "<commit>/<path:filename>/<row>",</row></path:filename></commit>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/"</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    "comment",
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/"</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    "comment/<commit>/<path:filename>/<row>",</row></path:filename></commit>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 880eeb
def pull_request_add_comment(
Pierre-Yves Chibon 9c2953
    repo,
Pierre-Yves Chibon 9c2953
    requestid,
Pierre-Yves Chibon 9c2953
    commit=None,
Pierre-Yves Chibon 9c2953
    filename=None,
Pierre-Yves Chibon 9c2953
    row=None,
Pierre-Yves Chibon 9c2953
    username=None,
Pierre-Yves Chibon 9c2953
    namespace=None,
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon cb10a1
    """ Add a comment to a commit in a pull-request.
Pierre-Yves Chibon cb10a1
    """
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon cb10a1
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-requests found for this project")
Pierre-Yves Chibon 3c6562
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon cb10a1
Pierre-Yves Chibon cb10a1
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
Pierre-Yves Chibon cb10a1
Pierre-Yves Chibon 9c2953
    is_js = flask.request.args.get("js", False)
Pierre-Yves Chibon 9c2953
    tree_id = flask.request.args.get("tree_id") or None
Patrick Uiterwijk 342340
Pierre-Yves Chibon fe5017
    form = pagure.forms.AddPullRequestCommentForm()
Pierre-Yves Chibon cb10a1
    form.commit.data = commit
Pierre-Yves Chibon abdb8f
    form.filename.data = filename
Pierre-Yves Chibon cb10a1
    form.requestid.data = requestid
Pierre-Yves Chibon cb10a1
    form.row.data = row
Pierre-Yves Chibon 444b61
    form.tree_id.data = tree_id
Pierre-Yves Chibon cb10a1
Pierre-Yves Chibon 248f5e
    if form.validate_on_submit():
Pierre-Yves Chibon 248f5e
        comment = form.comment.data
Pierre-Yves Chibon 248f5e
Pierre-Yves Chibon 248f5e
        try:
Slavek Kabrda a80d7c
            trigger_ci = pagure_config["TRIGGER_CI"]
Slavek Kabrda a80d7c
            if isinstance(trigger_ci, dict):
Slavek Kabrda a80d7c
                trigger_ci = list(trigger_ci.keys())
Pierre-Yves Chibon 930073
            message = pagure.lib.query.add_pull_request_comment(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon 248f5e
                request=request,
Pierre-Yves Chibon 248f5e
                commit=commit,
Pierre-Yves Chibon 444b61
                tree_id=tree_id,
Pierre-Yves Chibon abdb8f
                filename=filename,
Pierre-Yves Chibon 248f5e
                row=row,
Pierre-Yves Chibon 248f5e
                comment=comment,
Pierre-Yves Chibon 248f5e
                user=flask.g.fas_user.username,
Slavek Kabrda a80d7c
                trigger_ci=trigger_ci,
Pierre-Yves Chibon 248f5e
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 976f54
            if not is_js:
Pierre-Yves Chibon 976f54
                flask.flash(message)
Pierre-Yves Chibon fa97f7
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Patrick Uiterwijk 342340
            if is_js:
Pierre-Yves Chibon 9c2953
                return "error"
Pierre-Yves Chibon 36b67b
            else:
Pierre-Yves Chibon 9c2953
                flask.flash(str(err), "error")
Pierre-Yves Chibon 248f5e
Patrick Uiterwijk 342340
        if is_js:
Pierre-Yves Chibon 9c2953
            return "ok"
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon cb10a1
Pierre-Yves Chibon 9c2953
    if is_js and flask.request.method == "POST":
Pierre-Yves Chibon 9c2953
        return "failed"
Pierre-Yves Chibon 3c513d
Pierre-Yves Chibon cb10a1
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "pull_request_comment.html",
Pierre-Yves Chibon 9c2953
        select="requests",
Pierre-Yves Chibon cb10a1
        requestid=requestid,
Pierre-Yves Chibon cb10a1
        repo=repo,
Pierre-Yves Chibon cb10a1
        username=username,
Pierre-Yves Chibon cb10a1
        commit=commit,
Pierre-Yves Chibon 444b61
        tree_id=tree_id,
Pierre-Yves Chibon abdb8f
        filename=filename,
Pierre-Yves Chibon cb10a1
        row=row,
Pierre-Yves Chibon cb10a1
        form=form,
Pierre-Yves Chibon cb10a1
    )
Pierre-Yves Chibon cb10a1
Pierre-Yves Chibon cb10a1
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<repo>/pull-request/<int:requestid>/comment/drop", methods=["POST"]</int:requestid></repo>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/comment/drop",</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/comment/drop",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<namespace>/<username>/<repo>/pull-request/<int:requestid>/"</int:requestid></repo></username></namespace>
Pierre-Yves Chibon 9c2953
    "comment/drop",
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 9c2953
def pull_request_drop_comment(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon 6658de
    """ Delete a comment of a pull-request.
Pierre-Yves Chibon 6658de
    """
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon 6658de
farhaanbukhsh e9261e
    if not repo:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Project not found")
farhaanbukhsh 9ea58a
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-requests found for this project")
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon 6658de
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon 9c2953
    if flask.request.form.get("edit_comment"):
Pierre-Yves Chibon 9c2953
        commentid = flask.request.form.get("edit_comment")
Pierre-Yves Chibon bc01a9
        form = pagure.forms.EditCommentForm()
Pierre-Yves Chibon bc01a9
        if form.validate_on_submit():
Pierre-Yves Chibon bc01a9
            return pull_request_edit_comment(
Pierre-Yves Chibon 9c2953
                repo.name, requestid, commentid, username=username
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon bc01a9
Pierre-Yves Chibon 6658de
    form = pagure.forms.ConfirmationForm()
Pierre-Yves Chibon 6658de
    if form.validate_on_submit():
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon 9c2953
        if flask.request.form.get("drop_comment"):
Pierre-Yves Chibon 9c2953
            commentid = flask.request.form.get("drop_comment")
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon 930073
            comment = pagure.lib.query.get_request_comment(
Pierre-Yves Chibon 9c2953
                flask.g.session, request.uid, commentid
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon a482cb
            if comment is None or comment.pull_request.project != repo:
Pierre-Yves Chibon c6cc5c
                flask.abort(404, description="Comment not found")
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon 9c2953
            if (
Pierre-Yves Chibon 9c2953
                flask.g.fas_user.username != comment.user.username
Pierre-Yves Chibon 9c2953
                or comment.parent.status is False
Pierre-Yves Chibon 9c2953
            ) and not flask.g.repo_committer:
Pierre-Yves Chibon 6658de
                flask.abort(
Pierre-Yves Chibon 6658de
                    403,
Pierre-Yves Chibon c6cc5c
                    description="You are not allowed to remove this comment "
Pierre-Yves Chibon c6cc5c
                    "from this issue",
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon b130e5
            flask.g.session.delete(comment)
Pierre-Yves Chibon 6658de
            try:
Pierre-Yves Chibon b130e5
                flask.g.session.commit()
Pierre-Yves Chibon 9c2953
                flask.flash("Comment removed")
Pierre-Yves Chibon fa97f7
            except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
                flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
                _log.error(err)
Pierre-Yves Chibon 6658de
                flask.flash(
Pierre-Yves Chibon 9c2953
                    "Could not remove the comment: %s" % commentid, "error"
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon 9c2953
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for(
Pierre-Yves Chibon 9c2953
            "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
            username=username,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
            repo=repo.name,
Pierre-Yves Chibon 9c2953
            requestid=requestid,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon 6658de
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<repo>/pull-request/<int:requestid>/comment/<int:commentid>/edit",</int:commentid></int:requestid></repo>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/comment/"</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
    "<int:commentid>/edit",</int:commentid>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/comment"</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    "/<int:commentid>/edit",</int:commentid>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/"</repo></namespace></username>
Pierre-Yves Chibon 9c2953
    "<int:requestid>/comment/<int:commentid>/edit",</int:commentid></int:requestid>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 4501da
def pull_request_edit_comment(
Pierre-Yves Chibon 9c2953
    repo, requestid, commentid, username=None, namespace=None
Pierre-Yves Chibon 9c2953
):
farhaanbukhsh a04e02
    """Edit comment of a pull request
farhaanbukhsh a04e02
    """
Pierre-Yves Chibon 9c2953
    is_js = flask.request.args.get("js", False)
Pierre-Yves Chibon bc01a9
Pierre-Yves Chibon 319056
    project = flask.g.repo
farhaanbukhsh a04e02
Pierre-Yves Chibon 9c2953
    if not project.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-requests found for this project")
farhaanbukhsh a04e02
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=project.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
farhaanbukhsh a04e02
farhaanbukhsh a04e02
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
farhaanbukhsh a04e02
Pierre-Yves Chibon 930073
    comment = pagure.lib.query.get_request_comment(
Pierre-Yves Chibon 9c2953
        flask.g.session, request.uid, commentid
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 00872c
Pierre-Yves Chibon 00872c
    if comment is None or comment.parent.project != project:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Comment not found")
farhaanbukhsh a04e02
Pierre-Yves Chibon 9c2953
    if (
Pierre-Yves Chibon 9c2953
        flask.g.fas_user.username != comment.user.username
Pierre-Yves Chibon 9c2953
        or comment.parent.status != "Open"
Pierre-Yves Chibon 9c2953
    ) and not flask.g.repo_committer:
Pierre-Yves Chibon c6cc5c
        flask.abort(403, description="You are not allowed to edit the comment")
farhaanbukhsh a04e02
farhaanbukhsh a04e02
    form = pagure.forms.EditCommentForm()
farhaanbukhsh a04e02
farhaanbukhsh a04e02
    if form.validate_on_submit():
farhaanbukhsh a04e02
farhaanbukhsh a04e02
        updated_comment = form.update_comment.data
farhaanbukhsh a04e02
        try:
Pierre-Yves Chibon 930073
            message = pagure.lib.query.edit_comment(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon e0bf6d
                parent=request,
farhaanbukhsh a04e02
                comment=comment,
farhaanbukhsh a04e02
                user=flask.g.fas_user.username,
farhaanbukhsh a04e02
                updated_comment=updated_comment,
farhaanbukhsh a04e02
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 0ab13b
            if not is_js:
Pierre-Yves Chibon 0ab13b
                flask.flash(message)
Aurélien Bompard 831553
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.error(err)
Pierre-Yves Chibon 0ab13b
            if is_js:
Pierre-Yves Chibon 9c2953
                return "error"
Pierre-Yves Chibon 1cac34
            else:
Pierre-Yves Chibon 1cac34
                flask.flash(
Pierre-Yves Chibon 9c2953
                    "Could not edit the comment: %s" % commentid, "error"
Pierre-Yves Chibon 9c2953
                )
farhaanbukhsh a04e02
Pierre-Yves Chibon 0ab13b
        if is_js:
Pierre-Yves Chibon 9c2953
            return "ok"
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                repo=project.name,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
farhaanbukhsh a04e02
Pierre-Yves Chibon 9c2953
    if is_js and flask.request.method == "POST":
Pierre-Yves Chibon 9c2953
        return "failed"
Pierre-Yves Chibon 0ab13b
farhaanbukhsh a04e02
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "comment_update.html",
Pierre-Yves Chibon 9c2953
        select="requests",
farhaanbukhsh a04e02
        requestid=requestid,
farhaanbukhsh a04e02
        repo=project,
farhaanbukhsh a04e02
        username=username,
farhaanbukhsh a04e02
        form=form,
Pierre-Yves Chibon bc01a9
        comment=comment,
Pierre-Yves Chibon bc01a9
        is_js=is_js,
farhaanbukhsh a04e02
    )
farhaanbukhsh a04e02
farhaanbukhsh a04e02
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/<int:requestid>/reopen", methods=["POST"])</int:requestid></repo>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/reopen", methods=["POST"]</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
)
Karsten Hopp 130d0e
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/reopen",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Karsten Hopp 130d0e
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/reopen",</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Karsten Hopp 130d0e
@login_required
Karsten Hopp 130d0e
def reopen_request_pull(repo, requestid, username=None, namespace=None):
Karsten Hopp 130d0e
    """ Re-Open a pull request.
Karsten Hopp 130d0e
    """
Karsten Hopp 130d0e
    form = pagure.forms.ConfirmationForm()
Karsten Hopp 130d0e
    if form.validate_on_submit():
Karsten Hopp 130d0e
Pierre-Yves Chibon 9c2953
        if not flask.g.repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
            flask.abort(
Pierre-Yves Chibon c6cc5c
                404, description="No pull-requests found for this project"
Pierre-Yves Chibon c6cc5c
            )
Karsten Hopp 130d0e
Pierre-Yves Chibon 930073
        request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
            flask.g.session, project_id=flask.g.repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
        )
Karsten Hopp 130d0e
Karsten Hopp 130d0e
        if not request:
Pierre-Yves Chibon c6cc5c
            flask.abort(404, description="Pull-request not found")
Karsten Hopp 130d0e
Pierre-Yves Chibon 9c2953
        if (
Pierre-Yves Chibon 9c2953
            not flask.g.repo_committer
Pierre-Yves Chibon 9c2953
            and not flask.g.fas_user.username == request.user.username
Pierre-Yves Chibon 9c2953
        ):
Karsten Hopp 130d0e
            flask.abort(
Karsten Hopp 130d0e
                403,
Pierre-Yves Chibon c6cc5c
                description="You are not allowed to reopen pull-request "
Pierre-Yves Chibon c6cc5c
                "for this project",
Pierre-Yves Chibon 9c2953
            )
Karsten Hopp 130d0e
Karsten Hopp 130d0e
        try:
Pierre-Yves Chibon 930073
            pagure.lib.query.reopen_pull_request(
Patrick Uiterwijk 3f97f6
                flask.g.session, request, flask.g.fas_user.username
Pierre-Yves Chibon 9c2953
            )
Karsten Hopp 130d0e
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Karsten Hopp 130d0e
Karsten Hopp 130d0e
        try:
Karsten Hopp 130d0e
            flask.g.session.commit()
Pierre-Yves Chibon 9c2953
            flask.flash("Pull request reopened!")
Karsten Hopp 130d0e
        except SQLAlchemyError as err:  # pragma: no cover
Karsten Hopp 130d0e
            flask.g.session.rollback()
Karsten Hopp 130d0e
            _log.exception(err)
Karsten Hopp 130d0e
            flask.flash(
Pierre-Yves Chibon 9c2953
                "Could not update this pull-request in the database", "error"
Pierre-Yves Chibon 9c2953
            )
Karsten Hopp 130d0e
Karsten Hopp 130d0e
    else:
Pierre-Yves Chibon 9c2953
        flask.flash("Invalid input submitted", "error")
Karsten Hopp 130d0e
Pierre-Yves Chibon 9c2953
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for(
Pierre-Yves Chibon 9c2953
            "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
            repo=repo,
Pierre-Yves Chibon 9c2953
            username=username,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
            requestid=requestid,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Karsten Hopp 130d0e
Karsten Hopp 130d0e
Slavek Kabrda a80d7c
@UI_NS.route(
Pierre-Yves Chibon ee649a
    "/<repo>/pull-request/<int:requestid>/trigger-ci", methods=["POST"]</int:requestid></repo>
Slavek Kabrda a80d7c
)
Slavek Kabrda a80d7c
@UI_NS.route(
Slavek Kabrda a80d7c
    "/<namespace>/<repo>/pull-request/<int:requestid>/trigger-ci",</int:requestid></repo></namespace>
Pierre-Yves Chibon ee649a
    methods=["POST"],
Slavek Kabrda a80d7c
)
Slavek Kabrda a80d7c
@UI_NS.route(
Slavek Kabrda a80d7c
    "/fork/<username>/<repo>/pull-request/<int:requestid>/trigger-ci",</int:requestid></repo></username>
Slavek Kabrda a80d7c
    methods=["POST"],
Slavek Kabrda a80d7c
)
Slavek Kabrda a80d7c
@UI_NS.route(
Pierre-Yves Chibon ee649a
    (
Pierre-Yves Chibon ee649a
        "/fork/<username>/<namespace>/<repo>/pull-request/"</repo></namespace></username>
Pierre-Yves Chibon ee649a
        "<int:requestid>/trigger-ci"</int:requestid>
Pierre-Yves Chibon ee649a
    ),
Slavek Kabrda a80d7c
    methods=["POST"],
Slavek Kabrda a80d7c
)
Slavek Kabrda a80d7c
@login_required
Slavek Kabrda a80d7c
def ci_trigger_request_pull(repo, requestid, username=None, namespace=None):
Slavek Kabrda a80d7c
    """ Trigger CI testing for a PR.
Slavek Kabrda a80d7c
    """
Slavek Kabrda a80d7c
    form = pagure.forms.TriggerCIPRForm()
Slavek Kabrda a80d7c
    if not form.validate_on_submit():
Slavek Kabrda a80d7c
        flask.flash("Invalid input submitted", "error")
Slavek Kabrda a80d7c
        return flask.redirect(
Slavek Kabrda a80d7c
            flask.url_for(
Slavek Kabrda a80d7c
                "ui_ns.request_pull",
Slavek Kabrda a80d7c
                repo=repo,
Slavek Kabrda a80d7c
                requestid=requestid,
Slavek Kabrda a80d7c
                username=username,
Slavek Kabrda a80d7c
                namespace=namespace,
Slavek Kabrda a80d7c
            )
Slavek Kabrda a80d7c
        )
Slavek Kabrda a80d7c
Slavek Kabrda a80d7c
    repo_obj = flask.g.repo
Slavek Kabrda a80d7c
    request = pagure.lib.query.search_pull_requests(
Slavek Kabrda a80d7c
        flask.g.session, project_id=repo_obj.id, requestid=requestid
Slavek Kabrda a80d7c
    )
Slavek Kabrda a80d7c
Slavek Kabrda a80d7c
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
Slavek Kabrda a80d7c
Slavek Kabrda a80d7c
    trigger_ci = pagure_config["TRIGGER_CI"]
Slavek Kabrda a80d7c
    if isinstance(trigger_ci, dict):
Slavek Kabrda a80d7c
        trigger_ci = list(trigger_ci.keys())
Slavek Kabrda a80d7c
    pagure.lib.query.add_pull_request_comment(
Slavek Kabrda a80d7c
        flask.g.session,
Slavek Kabrda a80d7c
        request,
Slavek Kabrda a80d7c
        commit=None,
Slavek Kabrda a80d7c
        tree_id=None,
Slavek Kabrda a80d7c
        filename=None,
Slavek Kabrda a80d7c
        row=None,
Slavek Kabrda a80d7c
        comment=form.comment.data,
Slavek Kabrda a80d7c
        user=flask.g.fas_user.username,
Slavek Kabrda a80d7c
        notify=True,
Slavek Kabrda a80d7c
        notification=True,
Slavek Kabrda a80d7c
        trigger_ci=trigger_ci,
Slavek Kabrda a80d7c
    )
Slavek Kabrda a80d7c
Slavek Kabrda a80d7c
    return flask.redirect(
Slavek Kabrda a80d7c
        flask.url_for(
Slavek Kabrda a80d7c
            "ui_ns.request_pull",
Slavek Kabrda a80d7c
            repo=repo,
Slavek Kabrda a80d7c
            username=username,
Slavek Kabrda a80d7c
            namespace=namespace,
Slavek Kabrda a80d7c
            requestid=requestid,
Slavek Kabrda a80d7c
        )
Slavek Kabrda a80d7c
    )
Slavek Kabrda a80d7c
Slavek Kabrda a80d7c
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/<int:requestid>/merge", methods=["POST"])</int:requestid></repo>
Karsten Hopp 130d0e
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/merge", methods=["POST"]</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/merge",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/merge",</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 4501da
def merge_request_pull(repo, requestid, username=None, namespace=None):
Stanislav Laznicka 14c8c3
    """ Create a pull request with the changes from the fork into the project.
Pierre-Yves Chibon 47950c
    """
Johan Cwiklinski fd18bd
Lubomír Sedlář 7c6b11
    form = pagure.forms.MergePRForm()
Pierre-Yves Chibon 15e950
    if not form.validate_on_submit():
Pierre-Yves Chibon 9c2953
        flask.flash("Invalid input submitted", "error")
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                repo=repo,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Johan Cwiklinski fd18bd
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 59c651
    _log.info(
Pierre-Yves Chibon 9c2953
        "called merge_request_pull for repo: %s - requestid: %s",
Pierre-Yves Chibon 9c2953
        repo.fullname,
Pierre-Yves Chibon 9c2953
        requestid,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 59c651
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-requests found for this project")
Pierre-Yves Chibon 3c6562
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon b31474
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
Pierre-Yves Chibon 47950c
Vivek Anand 967335
    if not flask.g.repo_committer:
Pierre-Yves Chibon 4f2df5
        flask.abort(
Pierre-Yves Chibon c6cc5c
            403,
Pierre-Yves Chibon c6cc5c
            description="You are not allowed to merge pull-request "
Pierre-Yves Chibon c6cc5c
            "for this project",
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 4f2df5
Pierre-Yves Chibon 9c2953
    if repo.settings.get("Only_assignee_can_merge_pull-request", False):
Pierre-Yves Chibon 9ba2fa
        if not request.assignee:
Pierre-Yves Chibon 9c2953
            flask.flash("This request must be assigned to be merged", "error")
Pierre-Yves Chibon 9c2953
            return flask.redirect(
Pierre-Yves Chibon 9c2953
                flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    username=username,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                    repo=repo.name,
Pierre-Yves Chibon 9c2953
                    requestid=requestid,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9ba2fa
        if request.assignee.username != flask.g.fas_user.username:
Julen Landa Alustiza a51825
            flask.flash("Only the assignee can merge this request", "error")
Pierre-Yves Chibon 9c2953
            return flask.redirect(
Pierre-Yves Chibon 9c2953
                flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    username=username,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                    repo=repo.name,
Pierre-Yves Chibon 9c2953
                    requestid=requestid,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9ba2fa
Pierre-Yves Chibon 9c2953
    threshold = repo.settings.get("Minimum_score_to_merge_pull-request", -1)
Pierre-Yves Chibon 657351
    if threshold > 0 and int(request.score) < int(threshold):
Pierre-Yves Chibon 657351
        flask.flash(
Pierre-Yves Chibon 9c2953
            "This request does not have the minimum review score necessary "
Pierre-Yves Chibon 9c2953
            "to be merged",
Pierre-Yves Chibon 9c2953
            "error",
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 657351
Lubomír Sedlář 7c6b11
    if form.delete_branch.data:
Pierre-Yves Chibon 9c2953
        if not pagure_config.get("ALLOW_DELETE_BRANCH", True):
Lubomír Sedlář 7c6b11
            flask.flash(
Pierre-Yves Chibon 9c2953
                "This pagure instance does not allow branch deletion", "error"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
            return flask.redirect(
Pierre-Yves Chibon 9c2953
                flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    username=username,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                    repo=repo.name,
Pierre-Yves Chibon 9c2953
                    requestid=requestid,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            )
Lubomír Sedlář 7c6b11
        if not pagure.utils.is_repo_committer(request.project_from):
Lubomír Sedlář 7c6b11
            flask.flash(
Pierre-Yves Chibon 9c2953
                "You do not have permissions to delete the branch in the "
Pierre-Yves Chibon 9c2953
                "source repo",
Pierre-Yves Chibon 9c2953
                "error",
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
            return flask.redirect(
Pierre-Yves Chibon 9c2953
                flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    username=username,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                    repo=repo.name,
Pierre-Yves Chibon 9c2953
                    requestid=requestid,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            )
Lubomír Sedlář 7c6b11
        if request.remote_git:
Pierre-Yves Chibon 9c2953
            flask.flash("You can not delete branch in remote repo", "error")
Pierre-Yves Chibon 9c2953
            return flask.redirect(
Pierre-Yves Chibon 9c2953
                flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    username=username,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                    repo=repo.name,
Pierre-Yves Chibon 9c2953
                    requestid=requestid,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            )
Lubomír Sedlář 7c6b11
Pierre-Yves Chibon 9c2953
    _log.info("All checks in the controller passed")
Pierre-Yves Chibon 59c651
Pierre-Yves Chibon a2dd31
    try:
Pierre-Yves Chibon d4db02
        if flask.request.form.get("comment"):
Pierre-Yves Chibon 8821f7
            trigger_ci = pagure_config["TRIGGER_CI"]
Pierre-Yves Chibon 8821f7
            if isinstance(trigger_ci, dict):
Pierre-Yves Chibon 8821f7
                trigger_ci = list(trigger_ci.keys())
Pierre-Yves Chibon 8821f7
            message = pagure.lib.query.add_pull_request_comment(
Pierre-Yves Chibon 8821f7
                flask.g.session,
Pierre-Yves Chibon 8821f7
                request=request,
Pierre-Yves Chibon 8821f7
                commit=None,
Pierre-Yves Chibon 8821f7
                tree_id=None,
Pierre-Yves Chibon 8821f7
                filename=None,
Pierre-Yves Chibon 8821f7
                row=None,
Pierre-Yves Chibon d4db02
                comment=flask.request.form.get("comment"),
Pierre-Yves Chibon 8821f7
                user=flask.g.fas_user.username,
Pierre-Yves Chibon 8821f7
                trigger_ci=trigger_ci,
Pierre-Yves Chibon 8821f7
            )
Pierre-Yves Chibon 8821f7
            flask.g.session.commit()
Pierre-Yves Chibon 8821f7
            flask.flash(message)
Pierre-Yves Chibon 8821f7
Aurélien Bompard a7f281
        task = pagure.lib.tasks.merge_pull_request.delay(
Pierre-Yves Chibon 9c2953
            repo.name,
Pierre-Yves Chibon 9c2953
            namespace,
Pierre-Yves Chibon 9c2953
            username,
Pierre-Yves Chibon 9c2953
            requestid,
Lubomír Sedlář ed7075
            flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
            delete_branch_after=form.delete_branch.data,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon b130e5
        return pagure.utils.wait_for_task(
Aurélien Bompard a7f281
            task,
Pierre-Yves Chibon 9c2953
            prev=flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
            ),
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 8821f7
    except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon 8821f7
        flask.g.session.rollback()
Pierre-Yves Chibon 8821f7
        _log.exception(err)
Pierre-Yves Chibon 8821f7
        flask.flash(str(err), "error")
Pierre-Yves Chibon 8821f7
        return flask.redirect(
Pierre-Yves Chibon 8821f7
            flask.url_for(
Pierre-Yves Chibon 8821f7
                "ui_ns.request_pull",
Pierre-Yves Chibon 8821f7
                repo=repo.name,
Pierre-Yves Chibon 8821f7
                requestid=requestid,
Pierre-Yves Chibon 8821f7
                username=username,
Pierre-Yves Chibon 8821f7
                namespace=namespace,
Pierre-Yves Chibon 8821f7
            )
Pierre-Yves Chibon 8821f7
        )
Pierre-Yves Chibon 757a98
    except pygit2.GitError as err:
Pierre-Yves Chibon 9c2953
        _log.info("GitError exception raised")
Pierre-Yves Chibon 9c2953
        flask.flash("%s" % err, "error")
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 0aaeb1
    except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
        _log.info("PagureException exception raised")
Pierre-Yves Chibon 9c2953
        flask.flash(str(err), "error")
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon b31474
Pierre-Yves Chibon 9c2953
    _log.info("All fine, returning")
Pierre-Yves Chibon 9c2953
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for(
Pierre-Yves Chibon 9c2953
            "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
            repo=repo.name,
Pierre-Yves Chibon 9c2953
            username=username,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon a35061
@UI_NS.route("/<repo>/pull-request/close/<int:requestid>", methods=["POST"])</int:requestid></repo>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon a35061
    "/<namespace>/<repo>/pull-request/close/<int:requestid>", methods=["POST"]</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon a35061
    "/fork/<username>/<repo>/pull-request/close/<int:requestid>",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon a35061
    "/fork/<username>/<namespace>/<repo>/pull-request/close/<int:requestid>",</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon a35061
def close_request_pull(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon a35061
    """ Close a pull request without merging it.
Johan Cwiklinski 86d9c4
    """
Johan Cwiklinski fd18bd
Pierre-Yves Chibon fe5017
    form = pagure.forms.ConfirmationForm()
Pierre-Yves Chibon 15e950
    if form.validate_on_submit():
Johan Cwiklinski fd18bd
Pierre-Yves Chibon 9c2953
        if not flask.g.repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
            flask.abort(
Pierre-Yves Chibon c6cc5c
                404, description="No pull-requests found for this project"
Pierre-Yves Chibon c6cc5c
            )
Pierre-Yves Chibon 3c6562
Pierre-Yves Chibon 930073
        request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
            flask.g.session, project_id=flask.g.repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
        )
Johan Cwiklinski 86d9c4
Pierre-Yves Chibon 15e950
        if not request:
Pierre-Yves Chibon c6cc5c
            flask.abort(404, description="Pull-request not found")
Johan Cwiklinski 86d9c4
Pierre-Yves Chibon 9c2953
        if (
Pierre-Yves Chibon 9c2953
            not flask.g.repo_committer
Pierre-Yves Chibon 9c2953
            and not flask.g.fas_user.username == request.user.username
Pierre-Yves Chibon 9c2953
        ):
Clement Verna 140014
            flask.abort(
Clement Verna 140014
                403,
Pierre-Yves Chibon c6cc5c
                description="You are not allowed to close pull-request "
Pierre-Yves Chibon c6cc5c
                "for this project",
Pierre-Yves Chibon 9c2953
            )
Johan Cwiklinski 86d9c4
Pierre-Yves Chibon 930073
        pagure.lib.query.close_pull_request(
Patrick Uiterwijk 3f97f6
            flask.g.session, request, flask.g.fas_user.username, merged=False
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon d8fde8
        try:
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Julen Landa Alustiza 86bf39
            flask.flash("Pull request closed!")
Pierre-Yves Chibon d93787
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon d8fde8
            flask.flash(
Pierre-Yves Chibon 9c2953
                "Could not update this pull-request in the database", "error"
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 1cac34
Pierre-Yves Chibon 15e950
    else:
Pierre-Yves Chibon 9c2953
        flask.flash("Invalid input submitted", "error")
Johan Cwiklinski 86d9c4
Pierre-Yves Chibon 9c2953
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for(
Pierre-Yves Chibon 9c2953
            "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
            repo=repo,
Pierre-Yves Chibon 9c2953
            username=username,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Johan Cwiklinski 86d9c4
Johan Cwiklinski 86d9c4
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/refresh/<int:requestid>", methods=["POST"])</int:requestid></repo>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/refresh/<int:requestid>",</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/refresh/<int:requestid>",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/refresh/<int:requestid>",</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Patrick Uiterwijk 04c084
@login_required
Patrick Uiterwijk 04c084
def refresh_request_pull(repo, requestid, username=None, namespace=None):
Patrick Uiterwijk 04c084
    """ Refresh a remote pull request.
Patrick Uiterwijk 04c084
    """
Patrick Uiterwijk 04c084
Patrick Uiterwijk 04c084
    form = pagure.forms.ConfirmationForm()
Patrick Uiterwijk 04c084
    if form.validate_on_submit():
Patrick Uiterwijk 04c084
Pierre-Yves Chibon 9c2953
        if not flask.g.repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
            flask.abort(
Pierre-Yves Chibon c6cc5c
                404, description="No pull-requests found for this project"
Pierre-Yves Chibon c6cc5c
            )
Patrick Uiterwijk 04c084
Pierre-Yves Chibon 930073
        request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
            flask.g.session, project_id=flask.g.repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk 04c084
Patrick Uiterwijk 04c084
        if not request:
Pierre-Yves Chibon c6cc5c
            flask.abort(404, description="Pull-request not found")
Patrick Uiterwijk 04c084
Pierre-Yves Chibon 9c2953
        if (
Pierre-Yves Chibon 9c2953
            not flask.g.repo_committer
Pierre-Yves Chibon 9c2953
            and not flask.g.fas_user.username == request.user.username
Pierre-Yves Chibon 9c2953
        ):
Patrick Uiterwijk 04c084
            flask.abort(
Pierre-Yves Chibon c6cc5c
                403,
Pierre-Yves Chibon c6cc5c
                description="You are not allowed to refresh this pull request",
Pierre-Yves Chibon 9c2953
            )
Patrick Uiterwijk 04c084
Aurélien Bompard a7f281
        task = pagure.lib.tasks.refresh_remote_pr.delay(
Pierre-Yves Chibon 9c2953
            flask.g.repo.name, namespace, username, requestid
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon b130e5
        return pagure.utils.wait_for_task(
Aurélien Bompard a7f281
            task,
Pierre-Yves Chibon 9c2953
            prev=flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                repo=flask.g.repo.name,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                requestid=requestid,
Pierre-Yves Chibon 9c2953
            ),
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk 04c084
    else:
Pierre-Yves Chibon 9c2953
        flask.flash("Invalid input submitted", "error")
Patrick Uiterwijk 04c084
Pierre-Yves Chibon 9c2953
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for(
Pierre-Yves Chibon 9c2953
            "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
            username=username,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
            repo=flask.g.repo.name,
Pierre-Yves Chibon 9c2953
            requestid=requestid,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 04c084
Patrick Uiterwijk 04c084
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/pull-request/<int:requestid>/update", methods=["POST"])</int:requestid></repo>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/pull-request/<int:requestid>/update", methods=["POST"]</int:requestid></repo></namespace>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/pull-request/<int:requestid>/update",</int:requestid></repo></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/update",</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon c29244
def update_pull_requests(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon 9c2953
    """ Update the metadata of a pull-request. """
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon 621b17
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-request allowed on this project")
Pierre-Yves Chibon 621b17
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        flask.g.session, project_id=repo.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 621b17
Pierre-Yves Chibon 621b17
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Pull-request not found")
Pierre-Yves Chibon 621b17
Pierre-Yves Chibon 9c2953
    if (
Pierre-Yves Chibon a7717f
        not flask.g.repo_user
Pierre-Yves Chibon 9c2953
        and flask.g.fas_user.username != request.user.username
Pierre-Yves Chibon 9c2953
    ):
Pierre-Yves Chibon c6cc5c
        flask.abort(
Pierre-Yves Chibon c6cc5c
            403, description="You are not allowed to update this pull-request"
Pierre-Yves Chibon c6cc5c
        )
Ryan Lerch deaa7c
Pierre-Yves Chibon 43956c
    form = pagure.forms.ConfirmationForm()
Pierre-Yves Chibon 621b17
    if form.validate_on_submit():
Pierre-Yves Chibon c29244
        tags = [
Pierre-Yves Chibon c29244
            tag.strip()
Pierre-Yves Chibon 9c2953
            for tag in flask.request.form.get("tag", "").strip().split(",")
Pierre-Yves Chibon 9c2953
            if tag.strip()
Pierre-Yves Chibon 9c2953
        ]
Pierre-Yves Chibon c29244
Pierre-Yves Chibon c29244
        messages = set()
Pierre-Yves Chibon 621b17
        try:
Pierre-Yves Chibon c29244
            # Adjust (add/remove) tags
Pierre-Yves Chibon 930073
            msgs = pagure.lib.query.update_tags(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon b130e5
                obj=request,
Pierre-Yves Chibon b130e5
                tags=tags,
Pierre-Yves Chibon c29244
                username=flask.g.fas_user.username,
Pierre-Yves Chibon c29244
            )
Pierre-Yves Chibon c29244
            messages = messages.union(set(msgs))
Pierre-Yves Chibon c29244
Pierre-Yves Chibon a7717f
            if flask.g.repo_user:
Pierre-Yves Chibon c29244
                # Assign or update assignee of the ticket
Pierre-Yves Chibon 930073
                msg = pagure.lib.query.add_pull_request_assignee(
Pierre-Yves Chibon b130e5
                    flask.g.session,
Pierre-Yves Chibon c29244
                    request=request,
Pierre-Yves Chibon 9c2953
                    assignee=flask.request.form.get("user", "").strip()
Pierre-Yves Chibon 9c2953
                    or None,
Pierre-Yves Chibon c29244
                    user=flask.g.fas_user.username,
Pierre-Yves Chibon c29244
                )
Pierre-Yves Chibon c29244
                if msg:
Pierre-Yves Chibon c29244
                    messages.add(msg)
Pierre-Yves Chibon c29244
Pierre-Yves Chibon c29244
            if messages:
Pierre-Yves Chibon c29244
                # Add the comment for field updates:
Pierre-Yves Chibon 9c2953
                not_needed = set(["Comment added", "Updated comment"])
Pierre-Yves Chibon 930073
                pagure.lib.query.add_metadata_update_notif(
Pierre-Yves Chibon b130e5
                    session=flask.g.session,
Pierre-Yves Chibon c29244
                    obj=request,
Pierre-Yves Chibon c29244
                    messages=messages - not_needed,
Pierre-Yves Chibon c29244
                    user=flask.g.fas_user.username,
Pierre-Yves Chibon c29244
                )
Pierre-Yves Chibon 9c2953
                messages.add("Metadata fields updated")
Pierre-Yves Chibon c29244
Pierre-Yves Chibon b130e5
                flask.g.session.commit()
Pierre-Yves Chibon c29244
                for message in messages:
Pierre-Yves Chibon c29244
                    flask.flash(message)
Pierre-Yves Chibon b130e5
Pierre-Yves Chibon fa97f7
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 9c2953
            flask.flash("%s" % err, "error")
Pierre-Yves Chibon fa97f7
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
            _log.exception(err)
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon 621b17
Pierre-Yves Chibon 9c2953
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for(
Pierre-Yves Chibon 9c2953
            "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
            username=username,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
            repo=repo.name,
Pierre-Yves Chibon 9c2953
            requestid=requestid,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 621b17
Pierre-Yves Chibon 621b17
Pierre-Yves Chibon e04c77
# Specific actions
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 9c2953
@UI_NS.route("/do_fork/<repo>", methods=["POST"])</repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/do_fork/<namespace>/<repo>", methods=["POST"])</repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/do_fork/fork/<username>/<repo>", methods=["POST"])</repo></username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/do_fork/fork/<username>/<namespace>/<repo>", methods=["POST"])</repo></namespace></username>
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 4501da
def fork_project(repo, username=None, namespace=None):
Pierre-Yves Chibon fac0b1
    """ Fork the project specified into the user's namespace
Pierre-Yves Chibon fac0b1
    """
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon 80bba3
Pierre-Yves Chibon 0d6d0e
    form = pagure.forms.ConfirmationForm()
Pierre-Yves Chibon 0d6d0e
    if not form.validate_on_submit():
Pierre-Yves Chibon 0d6d0e
        flask.abort(400)
Pierre-Yves Chibon 0d6d0e
Pierre-Yves Chibon 930073
    if pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        flask.g.session,
Pierre-Yves Chibon 9c2953
        repo.name,
Pierre-Yves Chibon 9c2953
        user=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
        namespace=namespace,
Pierre-Yves Chibon 9c2953
    ):
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                username=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon ba3ab8
Pierre-Yves Chibon 80bba3
    try:
Pierre-Yves Chibon 930073
        task = pagure.lib.query.fork_project(
Patrick Uiterwijk 3f97f6
            session=flask.g.session, repo=repo, user=flask.g.fas_user.username
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 80bba3
Pierre-Yves Chibon b130e5
        flask.g.session.commit()
Pierre-Yves Chibon b130e5
        return pagure.utils.wait_for_task(
Aurélien Bompard a7f281
            task,
Pierre-Yves Chibon a95a67
            prev=flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                _external=True,
Pierre-Yves Chibon 9c2953
            ),
Pierre-Yves Chibon a95a67
        )
Pierre-Yves Chibon fa97f7
    except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
        flask.flash(str(err), "error")
Pierre-Yves Chibon fa97f7
    except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
        flask.g.session.rollback()
Pierre-Yves Chibon 9c2953
        flask.flash(str(err), "error")
Pierre-Yves Chibon 80bba3
Pierre-Yves Chibon 9c2953
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for(
Pierre-Yves Chibon 9c2953
            "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
            repo=repo.name,
Pierre-Yves Chibon 9c2953
            username=username,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon fac0b1
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<repo>/diff/<path:branch_to>..<path:branch_from>/",</path:branch_from></path:branch_to></repo>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<repo>/diff/<path:branch_to>..<path:branch_from>",</path:branch_from></path:branch_to></repo>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/diff/<path:branch_to>..<path:branch_from>/",</path:branch_from></path:branch_to></repo></namespace>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/diff/<path:branch_to>..<path:branch_from>",</path:branch_from></path:branch_to></repo></namespace>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/diff/<path:branch_to>..<path:branch_from>/",</path:branch_from></path:branch_to></repo></username>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/diff/<path:branch_to>..<path:branch_from>",</path:branch_from></path:branch_to></repo></username>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/diff/"</repo></namespace></username>
Pierre-Yves Chibon 9c2953
    "<path:branch_to>..<path:branch_from>/",</path:branch_from></path:branch_to>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/diff/"</repo></namespace></username>
Pierre-Yves Chibon 9c2953
    "<path:branch_to>..<path:branch_from>",</path:branch_from></path:branch_to>
Pierre-Yves Chibon 9c2953
    methods=("GET", "POST"),
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon 4501da
def new_request_pull(
Pierre-Yves Chibon 9c2953
    repo, branch_to, branch_from, username=None, namespace=None
Pierre-Yves Chibon 9c2953
):
Stanislav Laznicka 14c8c3
    """ Create a pull request with the changes from the fork into the project.
Pierre-Yves Chibon 82055c
    """
Pierre-Yves Chibon 9c2953
    branch_to = flask.request.values.get("branch_to", branch_to)
Pierre-Yves Chibon 9c2953
    project_to = flask.request.values.get("project_to")
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 495ee1
    parent = repo
Pierre-Yves Chibon 495ee1
    if repo.parent:
Pierre-Yves Chibon 495ee1
        parent = repo.parent
Pierre-Yves Chibon 495ee1
Pierre-Yves Chibon c457bb
    repo_obj = flask.g.repo_obj
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon d39de9
    if not project_to:
Pierre-Yves Chibon 78ba11
        parentpath = get_parent_repo_path(repo)
Pierre-Yves Chibon d39de9
        orig_repo = pygit2.Repository(parentpath)
Pierre-Yves Chibon d39de9
    else:
Pierre-Yves Chibon d39de9
        p_namespace = None
Pierre-Yves Chibon d39de9
        p_username = None
Pierre-Yves Chibon d39de9
        p_name = None
Pierre-Yves Chibon 9c2953
        project_to = project_to.rstrip("/")
Pierre-Yves Chibon 9c2953
        if project_to.startswith("fork/"):
Pierre-Yves Chibon 9c2953
            tmp = project_to.split("fork/")[1]
Pierre-Yves Chibon 9c2953
            p_username, left = tmp.split("/", 1)
Pierre-Yves Chibon d39de9
        else:
Pierre-Yves Chibon d39de9
            left = project_to
Pierre-Yves Chibon d39de9
Pierre-Yves Chibon 9c2953
        if "/" in left:
Pierre-Yves Chibon 9c2953
            p_namespace, p_name = left.split("/", 1)
Pierre-Yves Chibon d39de9
        else:
Pierre-Yves Chibon d39de9
            p_name = left
Pierre-Yves Chibon 930073
        parent = pagure.lib.query.get_authorized_project(
Pierre-Yves Chibon 9c2953
            flask.g.session, p_name, user=p_username, namespace=p_namespace
Pierre-Yves Chibon d39de9
        )
Pierre-Yves Chibon d39de9
        if parent:
Pierre-Yves Chibon d39de9
            family = [
Pierre-Yves Chibon 9c2953
                p.url_path
Pierre-Yves Chibon 930073
                for p in pagure.lib.query.get_project_family(
Pierre-Yves Chibon 930073
                    flask.g.session, repo
Pierre-Yves Chibon 930073
                )
Pierre-Yves Chibon d39de9
            ]
Pierre-Yves Chibon b8e102
            if parent.url_path not in family:
Pierre-Yves Chibon d39de9
                flask.abort(
Pierre-Yves Chibon d39de9
                    400,
Pierre-Yves Chibon c6cc5c
                    description="%s is not part of %s's family"
Pierre-Yves Chibon 9c2953
                    % (project_to, repo.url_path),
Pierre-Yves Chibon 9c2953
                )
Patrick Uiterwijk 3f97f6
            orig_repo = pygit2.Repository(parent.repopath("main"))
Pierre-Yves Chibon d39de9
        else:
Pierre-Yves Chibon c6cc5c
            flask.abort(
Pierre-Yves Chibon c6cc5c
                404, description="No project found for %s" % project_to
Pierre-Yves Chibon c6cc5c
            )
Pierre-Yves Chibon 82055c
Pierre-Yves Chibon 9c2953
    if not parent.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-request allowed on this project")
Pierre-Yves Chibon b8e102
Pierre-Yves Chibon b8e102
    if parent.settings.get(
Pierre-Yves Chibon 9c2953
        "Enforce_signed-off_commits_in_pull-request", False
Pierre-Yves Chibon 9c2953
    ):
Pierre-Yves Chibon b8e102
        flask.flash(
Pierre-Yves Chibon 9c2953
            "This project enforces the Signed-off-by statement on all "
Pierre-Yves Chibon 9c2953
            "commits"
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon b8e102
Pierre-Yves Chibon 6509a2
    try:
Pierre-Yves Chibon 875a08
        diff, diff_commits, orig_commit = pagure.lib.git.get_diff_info(
Pierre-Yves Chibon 9c2953
            repo_obj, orig_repo, branch_from, branch_to
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 6509a2
    except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon c6cc5c
        flask.abort(400, description=str(err))
Pierre-Yves Chibon 82055c
Vivek Anand 967335
    repo_committer = flask.g.repo_committer
Pierre-Yves Chibon abe299
Pierre-Yves Chibon fe5017
    form = pagure.forms.RequestPullForm()
Vivek Anand 967335
    if form.validate_on_submit() and repo_committer:
Pierre-Yves Chibon ac8023
        try:
Pierre-Yves Chibon 93cd1e
            if parent.settings.get(
Pierre-Yves Chibon 9c2953
                "Enforce_signed-off_commits_in_pull-request", False
Pierre-Yves Chibon 9c2953
            ):
Pierre-Yves Chibon d7c61c
                for commit in diff_commits:
Pierre-Yves Chibon 9c2953
                    if "signed-off-by" not in commit.message.lower():
Pierre-Yves Chibon d7c61c
                        raise pagure.exceptions.PagureException(
Pierre-Yves Chibon 9c2953
                            "This repo enforces that all commits are "
Pierre-Yves Chibon 9c2953
                            "signed off by their author. "
Pierre-Yves Chibon 9c2953
                        )
Pierre-Yves Chibon d7c61c
Pierre-Yves Chibon ac8023
            if orig_commit:
Pierre-Yves Chibon ac8023
                orig_commit = orig_commit.oid.hex
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 273d1b
            initial_comment = form.initial_comment.data.strip() or None
Pierre-Yves Chibon 922e4f
            commit_start = commit_stop = None
Pierre-Yves Chibon 922e4f
            if diff_commits:
Pierre-Yves Chibon 922e4f
                commit_stop = diff_commits[0].oid.hex
Pierre-Yves Chibon 922e4f
                commit_start = diff_commits[-1].oid.hex
Pierre-Yves Chibon 930073
            request = pagure.lib.query.new_pull_request(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon 6d60d2
                repo_to=parent,
Pierre-Yves Chibon 6d60d2
                branch_to=branch_to,
Pierre-Yves Chibon 6d60d2
                branch_from=branch_from,
Pierre-Yves Chibon ac8023
                repo_from=repo,
Pierre-Yves Chibon ac8023
                title=form.title.data,
Pierre-Yves Chibon 273d1b
                initial_comment=initial_comment,
Pierre-Yves Chibon e180e7
                allow_rebase=form.allow_rebase.data,
Pierre-Yves Chibon ac8023
                user=flask.g.fas_user.username,
Pierre-Yves Chibon 922e4f
                commit_start=commit_start,
Pierre-Yves Chibon 922e4f
                commit_stop=commit_stop,
Pierre-Yves Chibon ac8023
            )
Clement Verna 9b3fc8
Pierre-Yves Chibon d8fde8
            try:
Pierre-Yves Chibon b130e5
                flask.g.session.commit()
Pierre-Yves Chibon e3f425
            except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
                flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
                _log.exception(err)
Pierre-Yves Chibon d8fde8
                flask.flash(
Pierre-Yves Chibon 9c2953
                    "Could not register this pull-request in the database",
Pierre-Yves Chibon 9c2953
                    "error",
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 8399d1
Pierre-Yves Chibon 2c9e9f
            if not parent.is_fork:
Pierre-Yves Chibon 8399d1
                url = flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    requestid=request.id,
Pierre-Yves Chibon 9c2953
                    username=None,
Pierre-Yves Chibon 9c2953
                    repo=parent.name,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 8399d1
            else:
Pierre-Yves Chibon 8399d1
                url = flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    requestid=request.id,
Pierre-Yves Chibon 9c2953
                    username=parent.user.user,
Pierre-Yves Chibon 9c2953
                    repo=parent.name,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 8399d1
Pierre-Yves Chibon 8399d1
            return flask.redirect(url)
Pierre-Yves Chibon fa97f7
        except pagure.exceptions.PagureException as err:  # pragma: no cover
Pierre-Yves Chibon e3f425
            # There could be a PagureException thrown if the flask.g.fas_user
Pierre-Yves Chibon e3f425
            # wasn't in the DB but then it shouldn't be recognized as a
Pierre-Yves Chibon e3f425
            # repo admin and thus, if we ever are here, we are in trouble.
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon fa97f7
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon ac8023
Vivek Anand 967335
    if not flask.g.repo_committer:
Pierre-Yves Chibon e206e8
        form = None
Pierre-Yves Chibon e180e7
    elif flask.request.method == "GET":
Pierre-Yves Chibon e180e7
        form.allow_rebase.data = True
Pierre-Yves Chibon e206e8
Ryan Lerch e3d483
    # if the pull request we are creating only has one commit,
Ryan Lerch e3d483
    # we automatically fill out the form fields for the PR with
Ryan Lerch e3d483
    # the commit title and bodytext
Pierre-Yves Chibon 626e50
    if len(diff_commits) == 1 and form:
Pierre-Yves Chibon 9c2953
        form.title.data = diff_commits[0].message.strip().split("\n")[0]
Pierre-Yves Chibon 9c2953
        form.initial_comment.data = diff_commits[0].message.partition("\n")[2]
Maciej Lasyk 9de333
Pierre-Yves Chibon 87633f
    # Get the contributing templates from the requests git repo
Pierre-Yves Chibon 87633f
    contributing = None
Pierre-Yves Chibon 87633f
    requestrepopath = _get_parent_request_repo_path(repo)
Pierre-Yves Chibon 87633f
    if os.path.exists(requestrepopath):
Pierre-Yves Chibon 292f52
        requestrepo = pygit2.Repository(requestrepopath)
Pierre-Yves Chibon 292f52
        if not requestrepo.is_empty and not requestrepo.head_is_unborn:
Pierre-Yves Chibon 292f52
            commit = requestrepo[requestrepo.head.target]
Pierre-Yves Chibon 87633f
            contributing = __get_file_in_tree(
Pierre-Yves Chibon 9c2953
                requestrepo,
Pierre-Yves Chibon 9c2953
                commit.tree,
Pierre-Yves Chibon 9c2953
                ["templates", "contributing.md"],
Pierre-Yves Chibon 9c2953
                bail_on_tree=True,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 87633f
            if contributing:
Pierre-Yves Chibon 11d3da
                contributing, _ = pagure.doc_utils.convert_readme(
Pierre-Yves Chibon 9c2953
                    contributing.data, "md"
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 87633f
Pierre-Yves Chibon 74dadb
    flask.g.branches = sorted(orig_repo.listall_branches())
Pierre-Yves Chibon 74dadb
Ryan Lerch 92c2a8
    if diff:
Ryan Lerch 92c2a8
        diff.find_similar()
Ryan Lerch 92c2a8
Pierre-Yves Chibon 82055c
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "repo_new_pull_request.html",
Pierre-Yves Chibon 9c2953
        select="requests",
Pierre-Yves Chibon 82055c
        repo=repo,
Pierre-Yves Chibon 82055c
        username=username,
Pierre-Yves Chibon 82055c
        orig_repo=orig_repo,
Pierre-Yves Chibon d114c7
        parent_branches=sorted(flask.g.repo_obj.listall_branches()),
Pierre-Yves Chibon 82055c
        diff_commits=diff_commits,
Pierre-Yves Chibon 6d60d2
        diff=diff,
Pierre-Yves Chibon ac8023
        form=form,
Pierre-Yves Chibon 6d60d2
        branch_to=branch_to,
Pierre-Yves Chibon 6d60d2
        branch_from=branch_from,
Pierre-Yves Chibon 87633f
        contributing=contributing,
Pierre-Yves Chibon d39de9
        parent=parent,
Pierre-Yves Chibon d39de9
        project_to=project_to,
Pierre-Yves Chibon 82055c
    )
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/diff/remote/", methods=("GET", "POST"))</repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/diff/remote", methods=("GET", "POST"))</repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<namespace>/<repo>/diff/remote/", methods=("GET", "POST"))</repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<namespace>/<repo>/diff/remote", methods=("GET", "POST"))</repo></namespace>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<repo>/diff/remote/", methods=("GET", "POST"))</repo></username>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/fork/<username>/<repo>/diff/remote", methods=("GET", "POST"))</repo></username>
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/diff/remote/", methods=("GET", "POST")</repo></namespace></username>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/diff/remote", methods=("GET", "POST")</repo></namespace></username>
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon cf7f54
@login_required
Pierre-Yves Chibon 4501da
def new_remote_request_pull(repo, username=None, namespace=None):
Stanislav Laznicka 14c8c3
    """ Create a pull request with the changes from a remote fork into the
Stanislav Laznicka 14c8c3
        project.
Pierre-Yves Chibon e11763
    """
Pierre-Yves Chibon 9c2953
    confirm = flask.request.values.get("confirm", False)
Pierre-Yves Chibon e11763
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Pierre-Yves Chibon e11763
Pierre-Yves Chibon 77e84a
    if pagure_config.get("DISABLE_REMOTE_PR", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(
Pierre-Yves Chibon c6cc5c
            404, description="Remote pull-requests disabled on this server"
Pierre-Yves Chibon c6cc5c
        )
Karsten Hopp 9f48c1
Pierre-Yves Chibon 9c2953
    if not repo.settings.get("pull_requests", True):
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="No pull-request allowed on this project")
Pierre-Yves Chibon e11763
Pierre-Yves Chibon 9c2953
    if repo.settings.get("Enforce_signed-off_commits_in_pull-request", False):
Pierre-Yves Chibon 91d791
        flask.flash(
Pierre-Yves Chibon 9c2953
            "This project enforces the Signed-off-by statement on all "
Pierre-Yves Chibon 9c2953
            "commits"
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 91d791
Pierre-Yves Chibon c457bb
    orig_repo = flask.g.repo_obj
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
    form = pagure.forms.RemoteRequestPullForm()
Pierre-Yves Chibon 24c1d4
    if form.validate_on_submit():
Pierre-Yves Chibon 9c2953
        taskid = flask.request.values.get("taskid")
Patrick Uiterwijk c0c627
        if taskid:
Patrick Uiterwijk c0c627
            result = pagure.lib.tasks.get_result(taskid)
Patrick Uiterwijk c0c627
            if not result.ready:
Pierre-Yves Chibon b130e5
                return pagure.utils.wait_for_task_post(
Pierre-Yves Chibon 9c2953
                    taskid,
Pierre-Yves Chibon 9c2953
                    form,
Pierre-Yves Chibon 9c2953
                    "ui_ns.new_remote_request_pull",
Pierre-Yves Chibon 9c2953
                    repo=repo.name,
Pierre-Yves Chibon 9c2953
                    username=username,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                )
Patrick Uiterwijk c0c627
            # Make sure to collect any exceptions resulting from the task
Pierre-Yves Chibon 67fb44
            try:
Pierre-Yves Chibon 67fb44
                result.get(timeout=0)
Pierre-Yves Chibon 67fb44
            except Exception as err:
Pierre-Yves Chibon c6cc5c
                flask.abort(500, description=err)
Patrick Uiterwijk c0c627
Pierre-Yves Chibon e11763
        branch_from = form.branch_from.data.strip()
Pierre-Yves Chibon e11763
        branch_to = form.branch_to.data.strip()
Pierre-Yves Chibon e11763
        remote_git = form.git_repo.data.strip()
Pierre-Yves Chibon e11763
Pierre-Yves Chibon b9d537
        repopath = pagure.utils.get_remote_repo_path(remote_git, branch_from)
Patrick Uiterwijk c0c627
        if not repopath:
Patrick Uiterwijk c0c627
            taskid = pagure.lib.tasks.pull_remote_repo.delay(
Pierre-Yves Chibon 9c2953
                remote_git, branch_from
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon b130e5
            return pagure.utils.wait_for_task_post(
Pierre-Yves Chibon 9c2953
                taskid,
Pierre-Yves Chibon 9c2953
                form,
Pierre-Yves Chibon 9c2953
                "ui_ns.new_remote_request_pull",
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                username=username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                initial=True,
Pierre-Yves Chibon 9c2953
            )
Patrick Uiterwijk c0c627
Pierre-Yves Chibon e11763
        repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
        try:
Pierre-Yves Chibon 875a08
            diff, diff_commits, orig_commit = pagure.lib.git.get_diff_info(
Pierre-Yves Chibon 9c2953
                repo_obj, orig_repo, branch_from, branch_to
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon e11763
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
            flask.flash("%s" % err, "error")
Pierre-Yves Chibon 9c2953
            return flask.redirect(
Pierre-Yves Chibon 9c2953
                flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
                    username=username,
Pierre-Yves Chibon 9c2953
                    repo=repo.name,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
        if not confirm:
Pierre-Yves Chibon c457bb
            flask.g.branches = sorted(orig_repo.listall_branches())
Pierre-Yves Chibon e11763
            return flask.render_template(
Pierre-Yves Chibon 9c2953
                "repo_new_pull_request.html",
Pierre-Yves Chibon 9c2953
                select="requests",
Pierre-Yves Chibon 601947
                repo=repo,
Pierre-Yves Chibon 601947
                username=username,
Pierre-Yves Chibon 601947
                orig_repo=orig_repo,
Pierre-Yves Chibon 601947
                diff_commits=diff_commits,
Pierre-Yves Chibon 601947
                diff=diff,
Pierre-Yves Chibon 601947
                form=form,
Pierre-Yves Chibon 601947
                branch_to=branch_to,
Pierre-Yves Chibon 601947
                branch_from=branch_from,
Pierre-Yves Chibon 601947
                remote_git=remote_git,
Pierre-Yves Chibon 9873aa
                parent=repo,
Pierre-Yves Chibon 601947
            )
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
        try:
Pierre-Yves Chibon e11763
            if repo.settings.get(
Pierre-Yves Chibon 9c2953
                "Enforce_signed-off_commits_in_pull-request", False
Pierre-Yves Chibon 9c2953
            ):
Pierre-Yves Chibon e11763
                for commit in diff_commits:
Pierre-Yves Chibon 9c2953
                    if "signed-off-by" not in commit.message.lower():
Pierre-Yves Chibon e11763
                        raise pagure.exceptions.PagureException(
Pierre-Yves Chibon 9c2953
                            "This repo enforces that all commits are "
Pierre-Yves Chibon 9c2953
                            "signed off by their author. "
Pierre-Yves Chibon 9c2953
                        )
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
            if orig_commit:
Pierre-Yves Chibon e11763
                orig_commit = orig_commit.oid.hex
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
            parent = repo
Pierre-Yves Chibon e11763
            if repo.parent:
Pierre-Yves Chibon e11763
                parent = repo.parent
Pierre-Yves Chibon e11763
Pierre-Yves Chibon 930073
            request = pagure.lib.query.new_pull_request(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon e11763
                repo_to=parent,
Pierre-Yves Chibon e11763
                branch_to=branch_to,
Pierre-Yves Chibon e11763
                branch_from=branch_from,
Pierre-Yves Chibon e11763
                repo_from=None,
Pierre-Yves Chibon e11763
                remote_git=remote_git,
Pierre-Yves Chibon e11763
                title=form.title.data,
Pierre-Yves Chibon e11763
                user=flask.g.fas_user.username,
Pierre-Yves Chibon e11763
            )
Clement Verna f0a6d4
Pierre-Yves Chibon 9c2953
            if form.initial_comment.data.strip() != "":
Pierre-Yves Chibon 930073
                pagure.lib.query.add_pull_request_comment(
Pierre-Yves Chibon b130e5
                    flask.g.session,
Clement Verna f0a6d4
                    request=request,
Clement Verna f0a6d4
                    commit=None,
Clement Verna f0a6d4
                    tree_id=None,
Clement Verna f0a6d4
                    filename=None,
Clement Verna f0a6d4
                    row=None,
Clement Verna 320715
                    comment=form.initial_comment.data.strip(),
Clement Verna f0a6d4
                    user=flask.g.fas_user.username,
Clement Verna f0a6d4
                )
Clement Verna f0a6d4
Pierre-Yves Chibon e11763
            try:
Pierre-Yves Chibon b130e5
                flask.g.session.commit()
Pierre-Yves Chibon 9c2953
                flask.flash("Request created")
Pierre-Yves Chibon e11763
            except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
                flask.g.session.rollback()
Pierre-Yves Chibon 4635b5
                _log.exception(err)
Pierre-Yves Chibon e11763
                flask.flash(
Pierre-Yves Chibon 9c2953
                    "Could not register this pull-request in " "the database",
Pierre-Yves Chibon 9c2953
                    "error",
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
            if not parent.is_fork:
Pierre-Yves Chibon e11763
                url = flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    requestid=request.id,
Pierre-Yves Chibon 9c2953
                    username=None,
Pierre-Yves Chibon 9c2953
                    repo=parent.name,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon e11763
            else:
Pierre-Yves Chibon e11763
                url = flask.url_for(
Pierre-Yves Chibon 9c2953
                    "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
                    requestid=request.id,
Pierre-Yves Chibon 9c2953
                    username=parent.user,
Pierre-Yves Chibon 9c2953
                    repo=parent.name,
Pierre-Yves Chibon 9c2953
                    namespace=namespace,
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon e11763
Pierre-Yves Chibon e11763
            return flask.redirect(url)
Pierre-Yves Chibon fa97f7
        except pagure.exceptions.PagureException as err:  # pragma: no cover
Pierre-Yves Chibon e11763
            # There could be a PagureException thrown if the
Pierre-Yves Chibon e11763
            # flask.g.fas_user wasn't in the DB but then it shouldn't
Pierre-Yves Chibon e11763
            # be recognized as a repo admin and thus, if we ever are
Pierre-Yves Chibon e11763
            # here, we are in trouble.
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon fa97f7
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 9c2953
            flask.flash(str(err), "error")
Pierre-Yves Chibon e11763
Pierre-Yves Chibon c457bb
    flask.g.branches = sorted(orig_repo.listall_branches())
Pierre-Yves Chibon 7a6fff
    if flask.request.method == "GET":
Pierre-Yves Chibon 7a6fff
        try:
Pierre-Yves Chibon 7a6fff
            branch_to = orig_repo.head.shorthand
Pierre-Yves Chibon 7a6fff
        except pygit2.GitError:
Pierre-Yves Chibon 7a6fff
            branch_to = "master"
Pierre-Yves Chibon 7a6fff
    else:
Pierre-Yves Chibon 7a6fff
        branch_to = form.branch_to.data.strip()
Pierre-Yves Chibon c457bb
Pierre-Yves Chibon e11763
    return flask.render_template(
Pierre-Yves Chibon 9c2953
        "remote_pull_request.html",
Pierre-Yves Chibon 9c2953
        select="requests",
Pierre-Yves Chibon e11763
        repo=repo,
Pierre-Yves Chibon e11763
        username=username,
Pierre-Yves Chibon e11763
        form=form,
Pierre-Yves Chibon 59f36c
        branch_to=branch_to,
Pierre-Yves Chibon e11763
    )
Farhaan Bukhsh 43756f
Farhaan Bukhsh 43756f
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork_edit/<repo>/edit/<path:branchname>/f/<path:filename>",</path:filename></path:branchname></repo>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork_edit/<namespace>/<repo>/edit/<path:branchname>/f/<path:filename>",</path:filename></path:branchname></repo></namespace>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork_edit/fork/<username>/<repo>/edit/<path:branchname>/"</path:branchname></repo></username>
Pierre-Yves Chibon 9c2953
    "f/<path:filename>",</path:filename>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Pierre-Yves Chibon b130e5
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork_edit/fork/<username>/<namespace>/<repo>/edit/<path:branchname>/"</path:branchname></repo></namespace></username>
Pierre-Yves Chibon 9c2953
    "f/<path:filename>",</path:filename>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Farhaan Bukhsh 43756f
@login_required
Pierre-Yves Chibon 9c2953
def fork_edit_file(repo, branchname, filename, username=None, namespace=None):
Farhaan Bukhsh 43756f
    """ Fork the project specified and open the specific file to edit
Farhaan Bukhsh 43756f
    """
Pierre-Yves Chibon 319056
    repo = flask.g.repo
Farhaan Bukhsh 43756f
Farhaan Bukhsh 43756f
    form = pagure.forms.ConfirmationForm()
Farhaan Bukhsh 43756f
    if not form.validate_on_submit():
Farhaan Bukhsh 43756f
        flask.abort(400)
Farhaan Bukhsh 43756f
Pierre-Yves Chibon 930073
    if pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        flask.g.session,
Pierre-Yves Chibon 9c2953
        repo.name,
Pierre-Yves Chibon 9c2953
        namespace=repo.namespace,
Pierre-Yves Chibon 9c2953
        user=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
    ):
Pierre-Yves Chibon 9c2953
        flask.flash("You had already forked this project")
Pierre-Yves Chibon 9c2953
        return flask.redirect(
Pierre-Yves Chibon 9c2953
            flask.url_for(
Pierre-Yves Chibon 9c2953
                "ui_ns.edit_file",
Pierre-Yves Chibon 9c2953
                username=flask.g.fas_user.username,
Pierre-Yves Chibon 9c2953
                namespace=namespace,
Pierre-Yves Chibon 9c2953
                repo=repo.name,
Pierre-Yves Chibon 9c2953
                branchname=branchname,
Pierre-Yves Chibon 9c2953
                filename=filename,
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 9c2953
        )
Farhaan Bukhsh 43756f
Farhaan Bukhsh 43756f
    try:
Pierre-Yves Chibon 930073
        task = pagure.lib.query.fork_project(
Pierre-Yves Chibon b130e5
            session=flask.g.session,
Farhaan Bukhsh 43756f
            repo=repo,
Patrick Uiterwijk 2a3bd8
            user=flask.g.fas_user.username,
Patrick Uiterwijk 2a3bd8
            editbranch=branchname,
Pierre-Yves Chibon 9c2953
            editfile=filename,
Pierre-Yves Chibon 9c2953
        )
Farhaan Bukhsh 43756f
Pierre-Yves Chibon b130e5
        flask.g.session.commit()
Aurélien Bompard a7f281
        return pagure.utils.wait_for_task(task)
Farhaan Bukhsh 43756f
    except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 9c2953
        flask.flash(str(err), "error")
Farhaan Bukhsh 43756f
    except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
        flask.g.session.rollback()
Pierre-Yves Chibon 9c2953
        flask.flash(str(err), "error")
Farhaan Bukhsh 43756f
Pierre-Yves Chibon 9c2953
    return flask.redirect(
Pierre-Yves Chibon 9c2953
        flask.url_for(
Pierre-Yves Chibon 9c2953
            "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
            repo=repo.name,
Pierre-Yves Chibon 9c2953
            username=username,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
    )
Lubomír Sedlář 59889e
Lubomír Sedlář 59889e
Lubomír Sedlář 933908
_REACTION_URL_SNIPPET = (
Pierre-Yves Chibon 9c2953
    "pull-request/<int:requestid>/comment/<int:commentid>/react"</int:commentid></int:requestid>
Lubomír Sedlář 933908
)
Lubomír Sedlář 933908
Lubomír Sedlář 933908
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/%s/" % _REACTION_URL_SNIPPET, methods=["POST"])</repo>
Pierre-Yves Chibon 9c2953
@UI_NS.route("/<repo>/%s" % _REACTION_URL_SNIPPET, methods=["POST"])</repo>
Lubomír Sedlář 933908
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/%s/" % _REACTION_URL_SNIPPET, methods=["POST"]</repo></namespace>
Pierre-Yves Chibon 9c2953
)
Lubomír Sedlář 933908
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/<namespace>/<repo>/%s" % _REACTION_URL_SNIPPET, methods=["POST"]</repo></namespace>
Pierre-Yves Chibon 9c2953
)
Lubomír Sedlář 933908
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/%s/" % _REACTION_URL_SNIPPET, methods=["POST"]</repo></username>
Pierre-Yves Chibon 9c2953
)
Lubomír Sedlář 59889e
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<repo>/%s" % _REACTION_URL_SNIPPET, methods=["POST"]</repo></username>
Pierre-Yves Chibon 9c2953
)
Lubomír Sedlář 59889e
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/%s/" % _REACTION_URL_SNIPPET,</repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Lubomír Sedlář 59889e
@UI_NS.route(
Pierre-Yves Chibon 9c2953
    "/fork/<username>/<namespace>/<repo>/%s" % _REACTION_URL_SNIPPET,</repo></namespace></username>
Pierre-Yves Chibon 9c2953
    methods=["POST"],
Pierre-Yves Chibon 9c2953
)
Lubomír Sedlář 59889e
@login_required
Pierre-Yves Chibon 9c2953
def pull_request_comment_add_reaction(
Pierre-Yves Chibon 9c2953
    repo, requestid, commentid, username=None, namespace=None
Pierre-Yves Chibon 9c2953
):
Lubomír Sedlář 59889e
    repo = flask.g.repo
Lubomír Sedlář 59889e
Lubomír Sedlář 59889e
    form = pagure.forms.ConfirmationForm()
Lubomír Sedlář 59889e
    if not form.validate_on_submit():
Pierre-Yves Chibon c6cc5c
        flask.abort(400, description="CSRF token not valid")
Lubomír Sedlář 59889e
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Lubomír Sedlář 59889e
        flask.g.session, requestid=requestid, project_id=repo.id
Lubomír Sedlář 59889e
    )
Lubomír Sedlář 59889e
Lubomír Sedlář 59889e
    if not request:
Pierre-Yves Chibon c6cc5c
        flask.abort(404, description="Comment not found")
Lubomír Sedlář 59889e
Pierre-Yves Chibon 930073
    comment = pagure.lib.query.get_request_comment(
Pierre-Yves Chibon 9c2953
        flask.g.session, request.uid, commentid
Pierre-Yves Chibon 9c2953
    )
Lubomír Sedlář 59889e
Pierre-Yves Chibon 9c2953
    if "reaction" not in flask.request.form:
Pierre-Yves Chibon c6cc5c
        flask.abort(400, description="Reaction not found")
Lubomír Sedlář 59889e
Lubomír Sedlář 59889e
    reactions = comment.reactions
Pierre-Yves Chibon 9c2953
    r = flask.request.form["reaction"]
Lubomír Sedlář 59889e
    if not r:
Pierre-Yves Chibon c6cc5c
        flask.abort(400, description="Empty reaction is not acceptable")
Lubomír Sedlář 59889e
    if flask.g.fas_user.username in reactions.get(r, []):
Pierre-Yves Chibon c6cc5c
        flask.abort(409, description="Already posted this one")
Lubomír Sedlář 59889e
Lubomír Sedlář 59889e
    reactions.setdefault(r, []).append(flask.g.fas_user.username)
Lubomír Sedlář 59889e
    comment.reactions = reactions
Lubomír Sedlář 59889e
    flask.g.session.add(comment)
Lubomír Sedlář 59889e
Lubomír Sedlář 59889e
    try:
Lubomír Sedlář 59889e
        flask.g.session.commit()
Lubomír Sedlář 59889e
    except SQLAlchemyError as err:  # pragma: no cover
Lubomír Sedlář 59889e
        flask.g.session.rollback()
Lubomír Sedlář 59889e
        _log.error(err)
Pierre-Yves Chibon 9c2953
        return "error"
Lubomír Sedlář 59889e
Pierre-Yves Chibon 9c2953
    return "ok"