Blame pagure/api/fork.py

Pierre-Yves Chibon 1e1949
# -*- coding: utf-8 -*-
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
"""
Pierre-Yves Chibon b130e5
 (c) 2015-2017 - Copyright Red Hat Inc
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
 Authors:
Pierre-Yves Chibon 1e1949
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
"""
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
import flask
Pierre-Yves Chibon b130e5
import logging
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
from sqlalchemy.exc import SQLAlchemyError
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
import pagure
Pierre-Yves Chibon 1e1949
import pagure.exceptions
Pierre-Yves Chibon 1e1949
import pagure.lib
Patrick Uiterwijk e6f1fd
import pagure.lib.tasks
Patrick Uiterwijk eabc8e
from pagure.api import (API, api_method, api_login_required, APIERROR,
Patrick Uiterwijk eabc8e
                        get_authorized_api_project)
Pierre-Yves Chibon b130e5
from pagure.config import config as pagure_config
Pierre-Yves Chibon b130e5
from pagure.utils import is_repo_committer, api_authenticated
Pierre-Yves Chibon b130e5
Pierre-Yves Chibon b130e5
Pierre-Yves Chibon b130e5
_log = logging.getLogger(__name__)
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon c0cf15
@API.route('/<repo>/pull-requests')</repo>
Pierre-Yves Chibon 34ece4
@API.route('/<namespace>/<repo>/pull-requests')</repo></namespace>
Pierre-Yves Chibon c0cf15
@API.route('/fork/<username>/<repo>/pull-requests')</repo></username>
Pierre-Yves Chibon 34ece4
@API.route('/fork/<username>/<namespace>/<repo>/pull-requests')</repo></namespace></username>
Pierre-Yves Chibon c0cf15
@api_method
Pierre-Yves Chibon 34ece4
def api_pull_request_views(repo, username=None, namespace=None):
Pierre-Yves Chibon c0cf15
    """
Pierre-Yves Chibon c0cf15
    List project's Pull-Requests
Pierre-Yves Chibon c0cf15
    ----------------------------
Lei Yang 566c51
    Retrieve pull requests of a project.
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
    ::
Pierre-Yves Chibon c0cf15
Lei Yang 566c51
        GET /api/0/<repo>/pull-requests</repo>
Pierre-Yves Chibon 34ece4
        GET /api/0/<namespace>/<repo>/pull-requests</repo></namespace>
Pierre-Yves Chibon c0cf15
Lei Yang 566c51
    ::
Lei Yang 566c51
Lei Yang 566c51
        GET /api/0/fork/<username>/<repo>/pull-requests</repo></username>
Pierre-Yves Chibon 34ece4
        GET /api/0/fork/<username>/<namespace>/<repo>/pull-requests</repo></namespace></username>
Pierre-Yves Chibon c0cf15
Lei Yang 566c51
    Parameters
Lei Yang 566c51
    ^^^^^^^^^^
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon e1497f
    +---------------+----------+--------------+----------------------------+
Pierre-Yves Chibon e1497f
    | Key           | Type     | Optionality  | Description                |
Pierre-Yves Chibon e1497f
    +===============+==========+==============+============================+
Pierre-Yves Chibon e68983
    | ``status``    | string   | Optional     | | Filter the status of     |
Pierre-Yves Chibon e1497f
    |               |          |              |   pull requests. Default:  |
Pierre-Yves Chibon e1497f
    |               |          |              |   ``True`` (opened pull    |
Pierre-Yves Chibon e68983
    |               |          |              |   requests), can be ``0``  |
Pierre-Yves Chibon e68983
    |               |          |              |   or ``closed`` for closed |
Pierre-Yves Chibon e68983
    |               |          |              |   requests or ``Merged``   |
Pierre-Yves Chibon e68983
    |               |          |              |   for merged requests.     |
Eric Barbour 395fd2
    |               |          |              |   ``All`` returns closed,  |
Eric Barbour 395fd2
    |               |          |              |   merged and open requests.|
Pierre-Yves Chibon e1497f
    +---------------+----------+--------------+----------------------------+
Pierre-Yves Chibon e1497f
    | ``assignee``  | string   | Optional     | | Filter the assignee of   |
Pierre-Yves Chibon e1497f
    |               |          |              |   pull requests            |
Pierre-Yves Chibon e1497f
    +---------------+----------+--------------+----------------------------+
Pierre-Yves Chibon e1497f
    | ``author``    | string   | Optional     | | Filter the author of     |
Pierre-Yves Chibon e1497f
    |               |          |              |   pull requests            |
Pierre-Yves Chibon e1497f
    +---------------+----------+--------------+----------------------------+
Pierre-Yves Chibon c0cf15
Lei Yang 566c51
    Sample response
Lei Yang 566c51
    ^^^^^^^^^^^^^^^
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
    ::
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
        {
Pierre-Yves Chibon f3385b
          "args": {
Pierre-Yves Chibon f3385b
            "assignee": null,
Pierre-Yves Chibon f3385b
            "author": null,
Pierre-Yves Chibon f3385b
            "status": true
Pierre-Yves Chibon f3385b
          },
Pierre-Yves Chibon 7a734f
          "total_requests": 1,
Pierre-Yves Chibon f11edf
          "requests": [
Pierre-Yves Chibon f11edf
            {
Pierre-Yves Chibon f11edf
              "assignee": null,
Pierre-Yves Chibon f11edf
              "branch": "master",
Pierre-Yves Chibon f11edf
              "branch_from": "master",
Pierre-Yves Chibon 15c503
              "closed_at": null,
Pierre-Yves Chibon 15c503
              "closed_by": null,
Pierre-Yves Chibon f11edf
              "comments": [],
Pierre-Yves Chibon f11edf
              "commit_start": null,
Pierre-Yves Chibon f11edf
              "commit_stop": null,
Pierre-Yves Chibon f11edf
              "date_created": "1431414800",
Pierre-Yves Chibon f11edf
              "id": 1,
Pierre-Yves Chibon f11edf
              "project": {
Pierre-Yves Chibon f11edf
                "date_created": "1431414800",
Pierre-Yves Chibon f11edf
                "description": "test project #1",
Pierre-Yves Chibon f11edf
                "id": 1,
Pierre-Yves Chibon f11edf
                "name": "test",
Pierre-Yves Chibon f11edf
                "parent": null,
Pierre-Yves Chibon f11edf
                "user": {
Pierre-Yves Chibon f11edf
                  "fullname": "PY C",
Pierre-Yves Chibon f11edf
                  "name": "pingou"
Pierre-Yves Chibon f11edf
                }
Pierre-Yves Chibon f11edf
              },
Pierre-Yves Chibon f11edf
              "repo_from": {
Pierre-Yves Chibon f11edf
                "date_created": "1431414800",
Pierre-Yves Chibon f11edf
                "description": "test project #1",
Pierre-Yves Chibon f11edf
                "id": 1,
Pierre-Yves Chibon f11edf
                "name": "test",
Pierre-Yves Chibon f11edf
                "parent": null,
Pierre-Yves Chibon f11edf
                "user": {
Pierre-Yves Chibon f11edf
                  "fullname": "PY C",
Pierre-Yves Chibon f11edf
                  "name": "pingou"
Pierre-Yves Chibon f11edf
                }
Pierre-Yves Chibon f11edf
              },
Pierre-Yves Chibon 9e2f39
              "status": "Open",
Pierre-Yves Chibon f11edf
              "title": "test pull-request",
Pierre-Yves Chibon f11edf
              "uid": "1431414800",
Pierre-Yves Chibon e68983
              "updated_on": "1431414800",
Pierre-Yves Chibon f11edf
              "user": {
Pierre-Yves Chibon f11edf
                "fullname": "PY C",
Pierre-Yves Chibon f11edf
                "name": "pingou"
Pierre-Yves Chibon f11edf
              }
Pierre-Yves Chibon c0cf15
            }
Pierre-Yves Chibon f3385b
          ]
Pierre-Yves Chibon c0cf15
        }
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
    """
Pierre-Yves Chibon c0cf15
Patrick Uiterwijk eabc8e
    repo = get_authorized_api_project(
Pierre-Yves Chibon b130e5
        flask.g.session, repo, user=username, namespace=namespace)
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
    if repo is None:
Pierre-Yves Chibon c0cf15
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
    if not repo.settings.get('pull_requests', True):
Pierre-Yves Chibon 5ce0d9
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 5ce0d9
            404, error_code=APIERROR.EPULLREQUESTSDISABLED)
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
    status = flask.request.args.get('status', True)
Pierre-Yves Chibon c0cf15
    assignee = flask.request.args.get('assignee', None)
Pierre-Yves Chibon c0cf15
    author = flask.request.args.get('author', None)
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
    requests = []
Pierre-Yves Chibon e68983
    if str(status).lower() in ['0', 'false', 'closed']:
Pierre-Yves Chibon c0cf15
        requests = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
            flask.g.session,
Pierre-Yves Chibon c0cf15
            project_id=repo.id,
Pierre-Yves Chibon c0cf15
            status=False,
Pierre-Yves Chibon c0cf15
            assignee=assignee,
Pierre-Yves Chibon c0cf15
            author=author)
Eric Barbour 395fd2
Eric Barbour 395fd2
    elif str(status).lower() == 'all':
Eric Barbour 395fd2
        requests = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
            flask.g.session,
Eric Barbour 395fd2
            project_id=repo.id,
Eric Barbour 395fd2
            status=None,
Eric Barbour 395fd2
            assignee=assignee,
Eric Barbour 395fd2
            author=author)
Eric Barbour 395fd2
Pierre-Yves Chibon c0cf15
    else:
Pierre-Yves Chibon c0cf15
        requests = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
            flask.g.session,
Pierre-Yves Chibon c0cf15
            project_id=repo.id,
Pierre-Yves Chibon c0cf15
            assignee=assignee,
Pierre-Yves Chibon c0cf15
            author=author,
Pierre-Yves Chibon c0cf15
            status=status)
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
    jsonout = flask.jsonify({
Pierre-Yves Chibon 7a734f
        'total_requests': len(requests),
Pierre-Yves Chibon 87d805
        'requests': [
Pierre-Yves Chibon 87d805
            request.to_json(public=True, api=True)
Pierre-Yves Chibon 87d805
            for request in requests],
Pierre-Yves Chibon f3385b
        'args': {
Pierre-Yves Chibon f3385b
            'status': status,
Pierre-Yves Chibon f3385b
            'assignee': assignee,
Pierre-Yves Chibon f3385b
            'author': author,
Pierre-Yves Chibon f3385b
        }
Pierre-Yves Chibon c0cf15
    })
Pierre-Yves Chibon c0cf15
    return jsonout
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon c0cf15
Pierre-Yves Chibon bea7bd
@API.route('/<repo>/pull-request/<int:requestid>')</int:requestid></repo>
Pierre-Yves Chibon 34ece4
@API.route('/<namespace>/<repo>/pull-request/<int:requestid>')</int:requestid></repo></namespace>
Pierre-Yves Chibon bea7bd
@API.route('/fork/<username>/<repo>/pull-request/<int:requestid>')</int:requestid></repo></username>
Pierre-Yves Chibon 34ece4
@API.route('/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>')</int:requestid></repo></namespace></username>
Pierre-Yves Chibon bea7bd
@api_method
Pierre-Yves Chibon 34ece4
def api_pull_request_view(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon a6225b
    """
Pierre-Yves Chibon 1140cc
    Pull-request information
Pierre-Yves Chibon 1140cc
    ------------------------
Lei Yang 566c51
    Retrieve information of a specific pull request.
Pierre-Yves Chibon a6225b
Pierre-Yves Chibon a6225b
    ::
Pierre-Yves Chibon a6225b
Lei Yang 566c51
        GET /api/0/<repo>/pull-request/<request id=""></request></repo>
Pierre-Yves Chibon 34ece4
        GET /api/0/<namespace>/<repo>/pull-request/<request id=""></request></repo></namespace>
Pierre-Yves Chibon a6225b
Lei Yang 566c51
    ::
Pierre-Yves Chibon a6225b
Lei Yang 566c51
        GET /api/0/fork/<username>/<repo>/pull-request/<request id=""></request></repo></username>
Pierre-Yves Chibon 34ece4
        GET /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id=""></request></repo></namespace></username>
Pierre-Yves Chibon a6225b
Lei Yang 566c51
    Sample response
Lei Yang 566c51
    ^^^^^^^^^^^^^^^
Pierre-Yves Chibon a6225b
Pierre-Yves Chibon a6225b
    ::
Pierre-Yves Chibon a6225b
Pierre-Yves Chibon a6225b
        {
Pierre-Yves Chibon a6225b
          "assignee": null,
Pierre-Yves Chibon a6225b
          "branch": "master",
Pierre-Yves Chibon a6225b
          "branch_from": "master",
Pierre-Yves Chibon 15c503
          "closed_at": null,
Pierre-Yves Chibon 15c503
          "closed_by": null,
Pierre-Yves Chibon a6225b
          "comments": [],
Pierre-Yves Chibon a6225b
          "commit_start": null,
Pierre-Yves Chibon a6225b
          "commit_stop": null,
Pierre-Yves Chibon a6225b
          "date_created": "1431414800",
Pierre-Yves Chibon a6225b
          "id": 1,
Pierre-Yves Chibon a6225b
          "project": {
Farhaan Bukhsh ed34e5
            "close_status": [],
Farhaan Bukhsh ed34e5
            "custom_keys": [],
Pierre-Yves Chibon a6225b
            "date_created": "1431414800",
Pierre-Yves Chibon a6225b
            "description": "test project #1",
Pierre-Yves Chibon a6225b
            "id": 1,
Pierre-Yves Chibon a6225b
            "name": "test",
Pierre-Yves Chibon a6225b
            "parent": null,
Pierre-Yves Chibon a6225b
            "user": {
Pierre-Yves Chibon a6225b
              "fullname": "PY C",
Pierre-Yves Chibon a6225b
              "name": "pingou"
Pierre-Yves Chibon a6225b
            }
Pierre-Yves Chibon a6225b
          },
Pierre-Yves Chibon a6225b
          "repo_from": {
Pierre-Yves Chibon a6225b
            "date_created": "1431414800",
Pierre-Yves Chibon a6225b
            "description": "test project #1",
Pierre-Yves Chibon a6225b
            "id": 1,
Pierre-Yves Chibon a6225b
            "name": "test",
Pierre-Yves Chibon a6225b
            "parent": null,
Pierre-Yves Chibon a6225b
            "user": {
Pierre-Yves Chibon a6225b
              "fullname": "PY C",
Pierre-Yves Chibon a6225b
              "name": "pingou"
Pierre-Yves Chibon a6225b
            }
Pierre-Yves Chibon a6225b
          },
Pierre-Yves Chibon 9e2f39
          "status": "Open",
Pierre-Yves Chibon a6225b
          "title": "test pull-request",
Pierre-Yves Chibon a6225b
          "uid": "1431414800",
Pierre-Yves Chibon e68983
          "updated_on": "1431414800",
Pierre-Yves Chibon a6225b
          "user": {
Pierre-Yves Chibon a6225b
            "fullname": "PY C",
Pierre-Yves Chibon a6225b
            "name": "pingou"
Pierre-Yves Chibon a6225b
          }
Pierre-Yves Chibon a6225b
        }
Pierre-Yves Chibon a6225b
Pierre-Yves Chibon bea7bd
    """
Pierre-Yves Chibon bea7bd
Patrick Uiterwijk eabc8e
    repo = get_authorized_api_project(
Pierre-Yves Chibon b130e5
        flask.g.session, repo, user=username, namespace=namespace)
Pierre-Yves Chibon bea7bd
Pierre-Yves Chibon bea7bd
    if repo is None:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
Pierre-Yves Chibon bea7bd
Pierre-Yves Chibon bea7bd
    if not repo.settings.get('pull_requests', True):
Pierre-Yves Chibon 5ce0d9
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 5ce0d9
            404, error_code=APIERROR.EPULLREQUESTSDISABLED)
Pierre-Yves Chibon bea7bd
Pierre-Yves Chibon bea7bd
    request = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
        flask.g.session, project_id=repo.id, requestid=requestid)
Pierre-Yves Chibon bea7bd
Pierre-Yves Chibon bea7bd
    if not request:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOREQ)
Pierre-Yves Chibon bea7bd
Pierre-Yves Chibon 87d805
    jsonout = flask.jsonify(request.to_json(public=True, api=True))
Pierre-Yves Chibon bea7bd
    return jsonout
Pierre-Yves Chibon bea7bd
Pierre-Yves Chibon bea7bd
Pierre-Yves Chibon 807fce
@API.route('/<repo>/pull-request/<int:requestid>/merge', methods=['POST'])</int:requestid></repo>
Pierre-Yves Chibon 34ece4
@API.route(
Pierre-Yves Chibon 34ece4
    '/<namespace>/<repo>/pull-request/<int:requestid>/merge',</int:requestid></repo></namespace>
Pierre-Yves Chibon 34ece4
    methods=['POST'])
Pierre-Yves Chibon 807fce
@API.route('/fork/<username>/<repo>/pull-request/<int:requestid>/merge',</int:requestid></repo></username>
Pierre-Yves Chibon 807fce
           methods=['POST'])
Pierre-Yves Chibon 34ece4
@API.route(
Pierre-Yves Chibon 34ece4
    '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/merge',</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 34ece4
    methods=['POST'])
Pierre-Yves Chibon 807fce
@api_login_required(acls=['pull_request_merge'])
Pierre-Yves Chibon 807fce
@api_method
Pierre-Yves Chibon 34ece4
def api_pull_request_merge(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon be094c
    """
Pierre-Yves Chibon be094c
    Merge a pull-request
Pierre-Yves Chibon be094c
    --------------------
Lei Yang 566c51
    Instruct Paugre to merge a pull request.
Pierre-Yves Chibon be094c
Patrick Uiterwijk e6f1fd
    This is an asynchronous call.
Patrick Uiterwijk e6f1fd
Pierre-Yves Chibon be094c
    ::
Pierre-Yves Chibon be094c
Lei Yang 566c51
        POST /api/0/<repo>/pull-request/<request id="">/merge</request></repo>
Pierre-Yves Chibon 34ece4
        POST /api/0/<namespace>/<repo>/pull-request/<request id="">/merge</request></repo></namespace>
Pierre-Yves Chibon be094c
Lei Yang 566c51
    ::
Pierre-Yves Chibon be094c
Lei Yang 566c51
        POST /api/0/fork/<username>/<repo>/pull-request/<request id="">/merge</request></repo></username>
Pierre-Yves Chibon 34ece4
        POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id="">/merge</request></repo></namespace></username>
Pierre-Yves Chibon be094c
Lei Yang 566c51
    Sample response
Lei Yang 566c51
    ^^^^^^^^^^^^^^^
Pierre-Yves Chibon be094c
Pierre-Yves Chibon be094c
    ::
Pierre-Yves Chibon be094c
Patrick Uiterwijk 0281ff
        wait=False:
Pierre-Yves Chibon be094c
        {
Patrick Uiterwijk e6f1fd
          "message": "Merging queued",
Patrick Uiterwijk e6f1fd
          "taskid": "123-abcd"
Pierre-Yves Chibon be094c
        }
Pierre-Yves Chibon be094c
Patrick Uiterwijk 0281ff
        wait=True:
Patrick Uiterwijk 0281ff
        {
Patrick Uiterwijk 0281ff
          "message": "Changes merged!"
Patrick Uiterwijk 0281ff
        }
Patrick Uiterwijk 0281ff
Pierre-Yves Chibon 4768f2
    """  # noqa
Pierre-Yves Chibon 807fce
    output = {}
Pierre-Yves Chibon 807fce
Patrick Uiterwijk eabc8e
    repo = get_authorized_api_project(
Pierre-Yves Chibon b130e5
        flask.g.session, repo, user=username, namespace=namespace)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
    if repo is None:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
    if not repo.settings.get('pull_requests', True):
Pierre-Yves Chibon 5ce0d9
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 5ce0d9
            404, error_code=APIERROR.EPULLREQUESTSDISABLED)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon dea6ca
    if flask.g.token.project and repo != flask.g.token.project:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
    request = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
        flask.g.session, project_id=repo.id, requestid=requestid)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
    if not request:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOREQ)
Pierre-Yves Chibon 807fce
Vivek Anand 967335
    if not is_repo_committer(repo):
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(403, error_code=APIERROR.ENOPRCLOSE)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
    if repo.settings.get('Only_assignee_can_merge_pull-request', False):
Pierre-Yves Chibon 807fce
        if not request.assignee:
Pierre-Yves Chibon 53433f
            raise pagure.exceptions.APIError(
Pierre-Yves Chibon 53433f
                403, error_code=APIERROR.ENOTASSIGNED)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
        if request.assignee.username != flask.g.fas_user.username:
Pierre-Yves Chibon 704030
            raise pagure.exceptions.APIError(
Pierre-Yves Chibon 704030
                403, error_code=APIERROR.ENOTASSIGNEE)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
    threshold = repo.settings.get('Minimum_score_to_merge_pull-request', -1)
Pierre-Yves Chibon 807fce
    if threshold > 0 and int(request.score) < int(threshold):
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(403, error_code=APIERROR.EPRSCORE)
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
    try:
Patrick Uiterwijk e6f1fd
        taskid = pagure.lib.tasks.merge_pull_request.delay(
Patrick Uiterwijk e6f1fd
            repo.name, namespace, username, requestid,
Patrick Uiterwijk 0281ff
            flask.g.fas_user.username).id
Patrick Uiterwijk e6f1fd
        output = {'message': 'Merging queued',
Patrick Uiterwijk e6f1fd
                  'taskid': taskid}
Patrick Uiterwijk 0281ff
Patrick Uiterwijk 0281ff
        if flask.request.form.get('wait', True):
Patrick Uiterwijk 0281ff
            pagure.lib.tasks.get_result(taskid).get()
Patrick Uiterwijk 0281ff
            output = {'message': 'Changes merged!'}
Pierre-Yves Chibon 807fce
    except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon 807fce
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 2a7216
            400, error_code=APIERROR.ENOCODE, error=str(err))
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
    jsonout = flask.jsonify(output)
Pierre-Yves Chibon 807fce
    return jsonout
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 807fce
Pierre-Yves Chibon 291626
@API.route('/<repo>/pull-request/<int:requestid>/close', methods=['POST'])</int:requestid></repo>
Pierre-Yves Chibon 34ece4
@API.route(
Pierre-Yves Chibon 34ece4
    '/<namespace>/<repo>/pull-request/<int:requestid>/close',</int:requestid></repo></namespace>
Pierre-Yves Chibon 34ece4
    methods=['POST'])
Pierre-Yves Chibon 291626
@API.route('/fork/<username>/<repo>/pull-request/<int:requestid>/close',</int:requestid></repo></username>
Pierre-Yves Chibon 291626
           methods=['POST'])
Pierre-Yves Chibon 34ece4
@API.route(
Pierre-Yves Chibon 34ece4
    '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/close',</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 34ece4
    methods=['POST'])
Pierre-Yves Chibon 291626
@api_login_required(acls=['pull_request_close'])
Pierre-Yves Chibon 291626
@api_method
Pierre-Yves Chibon 34ece4
def api_pull_request_close(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon 2da4df
    """
Pierre-Yves Chibon 2da4df
    Close a pull-request
Pierre-Yves Chibon 2da4df
    --------------------
Lei Yang 566c51
    Instruct Pagure to close a pull request.
Pierre-Yves Chibon 2da4df
Pierre-Yves Chibon 2da4df
    ::
Pierre-Yves Chibon 2da4df
Lei Yang 566c51
        POST /api/0/<repo>/pull-request/<request id="">/close</request></repo>
Pierre-Yves Chibon 34ece4
        POST /api/0/<namespace>/<repo>/pull-request/<request id="">/close</request></repo></namespace>
Pierre-Yves Chibon 2da4df
Lei Yang 566c51
    ::
Pierre-Yves Chibon 2da4df
Lei Yang 566c51
        POST /api/0/fork/<username>/<repo>/pull-request/<request id="">/close</request></repo></username>
Pierre-Yves Chibon 34ece4
        POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id="">/close</request></repo></namespace></username>
Pierre-Yves Chibon 2da4df
Lei Yang 566c51
    Sample response
Lei Yang 566c51
    ^^^^^^^^^^^^^^^
Pierre-Yves Chibon 2da4df
Pierre-Yves Chibon 2da4df
    ::
Pierre-Yves Chibon 2da4df
Pierre-Yves Chibon 2da4df
        {
Pierre-Yves Chibon 369fd6
          "message": "Pull-request closed!"
Pierre-Yves Chibon 2da4df
        }
Pierre-Yves Chibon 2da4df
Pierre-Yves Chibon 4768f2
    """  # noqa
Pierre-Yves Chibon 291626
    output = {}
Pierre-Yves Chibon 291626
Patrick Uiterwijk eabc8e
    repo = get_authorized_api_project(
Pierre-Yves Chibon b130e5
        flask.g.session, repo, user=username, namespace=namespace)
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 291626
    if repo is None:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 291626
    if not repo.settings.get('pull_requests', True):
Pierre-Yves Chibon 5ce0d9
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 5ce0d9
            404, error_code=APIERROR.EPULLREQUESTSDISABLED)
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 291626
    if repo != flask.g.token.project:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK)
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 291626
    request = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
        flask.g.session, project_id=repo.id, requestid=requestid)
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 291626
    if not request:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOREQ)
Pierre-Yves Chibon 291626
Vivek Anand 967335
    if not is_repo_committer(repo):
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(403, error_code=APIERROR.ENOPRCLOSE)
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 291626
    try:
Pierre-Yves Chibon 035e9b
        pagure.lib.close_pull_request(
Pierre-Yves Chibon b130e5
            flask.g.session, request, flask.g.fas_user.username,
Pierre-Yves Chibon b130e5
            requestfolder=pagure_config['REQUESTS_FOLDER'],
Pierre-Yves Chibon 035e9b
            merged=False)
Pierre-Yves Chibon b130e5
        flask.g.session.commit()
Pierre-Yves Chibon 369fd6
        output['message'] = 'Pull-request closed!'
Pierre-Yves Chibon 291626
    except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
        flask.g.session.rollback()
Pierre-Yves Chibon b130e5
        _log.exception(err)
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 291626
    jsonout = flask.jsonify(output)
Pierre-Yves Chibon 291626
    return jsonout
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 291626
Pierre-Yves Chibon 1e1949
@API.route('/<repo>/pull-request/<int:requestid>/comment',</int:requestid></repo>
Pierre-Yves Chibon 1e1949
           methods=['POST'])
Pierre-Yves Chibon 34ece4
@API.route('/<namespace>/<repo>/pull-request/<int:requestid>/comment',</int:requestid></repo></namespace>
Pierre-Yves Chibon 34ece4
           methods=['POST'])
Pierre-Yves Chibon 1e1949
@API.route('/fork/<username>/<repo>/pull-request/<int:requestid>/comment',</int:requestid></repo></username>
Pierre-Yves Chibon 1e1949
           methods=['POST'])
Pierre-Yves Chibon 34ece4
@API.route(
Pierre-Yves Chibon 34ece4
    '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/comment',</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 34ece4
    methods=['POST'])
Pierre-Yves Chibon 1e1949
@api_login_required(acls=['pull_request_comment'])
Pierre-Yves Chibon 1e1949
@api_method
Pierre-Yves Chibon 34ece4
def api_pull_request_add_comment(
Pierre-Yves Chibon 34ece4
        repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon e91c31
    """
Pierre-Yves Chibon e91c31
    Comment on a pull-request
Pierre-Yves Chibon 47edc6
    -------------------------
Lei Yang 566c51
    Add comment to a pull request.
Pierre-Yves Chibon e91c31
Pierre-Yves Chibon e91c31
    ::
Pierre-Yves Chibon e91c31
Lei Yang 566c51
        POST /api/0/<repo>/pull-request/<request id="">/comment</request></repo>
Pierre-Yves Chibon 34ece4
        POST /api/0/<namespace>/<repo>/pull-request/<request id="">/comment</request></repo></namespace>
Lei Yang 566c51
Lei Yang 566c51
    ::
Pierre-Yves Chibon e91c31
Lei Yang 566c51
        POST /api/0/fork/<username>/<repo>/pull-request/<request id="">/comment</request></repo></username>
Pierre-Yves Chibon 34ece4
        POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id="">/comment</request></repo></namespace></username>
Pierre-Yves Chibon e91c31
Lei Yang 566c51
    Input
Lei Yang 566c51
    ^^^^^
Pierre-Yves Chibon e91c31
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e1497f
    | Key           | Type    | Optionality  | Description                 |
Pierre-Yves Chibon e1497f
    +===============+=========+==============+=============================+
Pierre-Yves Chibon e1497f
    | ``comment``   | string  | Mandatory    | | The comment to add        |
Pierre-Yves Chibon e1497f
    |               |         |              |   to the pull request       |
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e1497f
    | ``commit``    | string  | Optional     | | The hash of the specific  |
Pierre-Yves Chibon e1497f
    |               |         |              |   commit you wish to        |
Pierre-Yves Chibon e1497f
    |               |         |              |   comment on                |
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e1497f
    | ``filename``  | string  | Optional     | | The filename of the       |
Pierre-Yves Chibon e1497f
    |               |         |              |   specific file you wish    |
Pierre-Yves Chibon e1497f
    |               |         |              |   to comment on             |
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e1497f
    | ``row``       | int     | Optional     | | Used in combination       |
Pierre-Yves Chibon e1497f
    |               |         |              |   with filename to comment  |
Pierre-Yves Chibon e1497f
    |               |         |              |   on a specific row         |
Pierre-Yves Chibon e1497f
    |               |         |              |   of a file                 |
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon 626dba
    | ``tree_id``   | string  | Optional     | | The identifier of the     |
Pierre-Yves Chibon 626dba
    |               |         |              |   git tree as it was when   |
Pierre-Yves Chibon 626dba
    |               |         |              |   the comment was added     |
Pierre-Yves Chibon 626dba
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e91c31
Lei Yang 566c51
    Sample response
Lei Yang 566c51
    ^^^^^^^^^^^^^^^
Pierre-Yves Chibon e91c31
Pierre-Yves Chibon e91c31
    ::
Pierre-Yves Chibon e91c31
Pierre-Yves Chibon e91c31
        {
Pierre-Yves Chibon e91c31
          "message": "Comment added"
Pierre-Yves Chibon e91c31
        }
Pierre-Yves Chibon e91c31
Pierre-Yves Chibon 4768f2
    """  # noqa
Patrick Uiterwijk eabc8e
    repo = get_authorized_api_project(
Pierre-Yves Chibon b130e5
        flask.g.session, repo, user=username, namespace=namespace)
farhaanbukhsh 44a97a
Pierre-Yves Chibon 1e1949
    output = {}
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
    if repo is None:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
    if not repo.settings.get('pull_requests', True):
Pierre-Yves Chibon 5ce0d9
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 5ce0d9
            404, error_code=APIERROR.EPULLREQUESTSDISABLED)
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1dfd94
    if flask.g.token.project and repo != flask.g.token.project:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK)
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
    request = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
        flask.g.session, project_id=repo.id, requestid=requestid)
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
    if not request:
Pierre-Yves Chibon 23d3ff
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOREQ)
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
    form = pagure.forms.AddPullRequestCommentForm(csrf_enabled=False)
Pierre-Yves Chibon 1e1949
    if form.validate_on_submit():
Pierre-Yves Chibon 1e1949
        comment = form.comment.data
Pierre-Yves Chibon 551952
        commit = form.commit.data or None
Pierre-Yves Chibon 551952
        filename = form.filename.data or None
Pierre-Yves Chibon 626dba
        tree_id = form.tree_id.data or None
Pierre-Yves Chibon 551952
        row = form.row.data or None
Pierre-Yves Chibon 1e1949
        try:
Pierre-Yves Chibon 1e1949
            # New comment
Pierre-Yves Chibon 1e1949
            message = pagure.lib.add_pull_request_comment(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon 1e1949
                request=request,
Pierre-Yves Chibon 1e1949
                commit=commit,
Pierre-Yves Chibon 626dba
                tree_id=tree_id,
Pierre-Yves Chibon 1e1949
                filename=filename,
Pierre-Yves Chibon 1e1949
                row=row,
Pierre-Yves Chibon 1e1949
                comment=comment,
Pierre-Yves Chibon 1e1949
                user=flask.g.fas_user.username,
Pierre-Yves Chibon b130e5
                requestfolder=pagure_config['REQUESTS_FOLDER'],
Pierre-Yves Chibon 1e1949
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 1e1949
            output['message'] = message
Pierre-Yves Chibon d47179
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon d47179
            raise pagure.exceptions.APIError(
Pierre-Yves Chibon d47179
                400, error_code=APIERROR.ENOCODE, error=str(err))
Pierre-Yves Chibon fa97f7
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            _log.exception(err)
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon 23d3ff
            raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
    else:
Pierre-Yves Chibon f7fcaa
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon f7fcaa
            400, error_code=APIERROR.EINVALIDREQ, errors=form.errors)
Pierre-Yves Chibon 1e1949
Pierre-Yves Chibon 1e1949
    jsonout = flask.jsonify(output)
Pierre-Yves Chibon 1e1949
    return jsonout
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
@API.route('/<repo>/pull-request/<int:requestid>/flag',</int:requestid></repo>
Pierre-Yves Chibon e39f18
           methods=['POST'])
Pierre-Yves Chibon 34ece4
@API.route('/<namespace>/<repo>/pull-request/<int:requestid>/flag',</int:requestid></repo></namespace>
Pierre-Yves Chibon 34ece4
           methods=['POST'])
Pierre-Yves Chibon e39f18
@API.route('/fork/<username>/<repo>/pull-request/<int:requestid>/flag',</int:requestid></repo></username>
Pierre-Yves Chibon e39f18
           methods=['POST'])
Pierre-Yves Chibon 34ece4
@API.route(
Pierre-Yves Chibon 34ece4
    '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>/flag',</int:requestid></repo></namespace></username>
Pierre-Yves Chibon 34ece4
    methods=['POST'])
Pierre-Yves Chibon e39f18
@api_login_required(acls=['pull_request_flag'])
Pierre-Yves Chibon e39f18
@api_method
Pierre-Yves Chibon 34ece4
def api_pull_request_add_flag(repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon e39f18
    """
Pierre-Yves Chibon e39f18
    Flag a pull-request
Pierre-Yves Chibon e39f18
    -------------------
Lei Yang 566c51
    Add or edit flags on a pull-request.
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
    ::
Pierre-Yves Chibon e39f18
Lei Yang 566c51
        POST /api/0/<repo>/pull-request/<request id="">/flag</request></repo>
Pierre-Yves Chibon 34ece4
        POST /api/0/<namespace>/<repo>/pull-request/<request id="">/flag</request></repo></namespace>
Lei Yang 566c51
Lei Yang 566c51
    ::
Lei Yang 566c51
Lei Yang 566c51
        POST /api/0/fork/<username>/<repo>/pull-request/<request id="">/flag</request></repo></username>
Pierre-Yves Chibon 34ece4
        POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id="">/flag</request></repo></namespace></username>
Lei Yang 566c51
Lei Yang 566c51
    Input
Lei Yang 566c51
    ^^^^^
Lei Yang 566c51
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e1497f
    | Key           | Type    | Optionality  | Description                 |
Pierre-Yves Chibon e1497f
    +===============+=========+==============+=============================+
Pierre-Yves Chibon e1497f
    | ``username``  | string  | Mandatory    | | The name of the           |
Pierre-Yves Chibon e1497f
    |               |         |              |   application to be         |
Pierre-Yves Chibon e1497f
    |               |         |              |   presented to users        |
Pierre-Yves Chibon e1497f
    |               |         |              |   on the pull request page  |
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e1497f
    | ``comment``   | string  | Mandatory    | | A short message           |
Pierre-Yves Chibon e1497f
    |               |         |              |   summarizing the           |
Pierre-Yves Chibon e1497f
    |               |         |              |   presented results         |
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e1497f
    | ``url``       | string  | Mandatory    | | A URL to the result       |
Pierre-Yves Chibon e1497f
    |               |         |              |   of this flag              |
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon abcbf7
    | ``status``    | string  | Optional     | | The status of the task,   |
Pierre-Yves Chibon abcbf7
    |               |         |              |   can be any of: success,   |
Pierre-Yves Chibon abcbf7
    |               |         |              |   failure, error, pending,  |
Pierre-Yves Chibon abcbf7
    |               |         |              |   canceled                  |
Pierre-Yves Chibon abcbf7
    |               |         |              |   If not provided it will be|
Pierre-Yves Chibon abcbf7
    |               |         |              |   set to ``success`` if     |
Pierre-Yves Chibon abcbf7
    |               |         |              |   percent is higher than 0, |
Pierre-Yves Chibon abcbf7
    |               |         |              |   ``failure`` if it is 0 and|
Pierre-Yves Chibon abcbf7
    |               |         |              |   ``pending`` if percent is |
Pierre-Yves Chibon abcbf7
    |               |         |              |   not specified             |
Pierre-Yves Chibon abcbf7
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon abcbf7
    | ``percent``   | int     | Optional     | | A percentage of           |
Pierre-Yves Chibon abcbf7
    |               |         |              |   completion compared to    |
Pierre-Yves Chibon abcbf7
    |               |         |              |   the goal. The percentage  |
Pierre-Yves Chibon abcbf7
    |               |         |              |   also determine the        |
Pierre-Yves Chibon abcbf7
    |               |         |              |   background color of the   |
Pierre-Yves Chibon abcbf7
    |               |         |              |   flag on the pull-request  |
Pierre-Yves Chibon abcbf7
    |               |         |              |   page                      |
Pierre-Yves Chibon abcbf7
    +---------------+---------+--------------+-----------------------------+
Pierre-Yves Chibon e1497f
    | ``uid``       | string  | Optional     | | A unique identifier used  |
Pierre-Yves Chibon e1497f
    |               |         |              |   to identify a flag on a   |
Pierre-Yves Chibon e1497f
    |               |         |              |   pull-request. If the      |
Pierre-Yves Chibon e1497f
    |               |         |              |   provided UID matches an   |
Pierre-Yves Chibon e1497f
    |               |         |              |   existing one, then the    |
Pierre-Yves Chibon e1497f
    |               |         |              |   API call will update the  |
Pierre-Yves Chibon e1497f
    |               |         |              |   existing one rather than  |
Pierre-Yves Chibon e1497f
    |               |         |              |   create a new one.         |
Pierre-Yves Chibon e1497f
    |               |         |              |   Maximum Length: 32        |
Pierre-Yves Chibon e1497f
    |               |         |              |   characters. Default: an   |
Pierre-Yves Chibon e1497f
    |               |         |              |   auto generated UID        |
Pierre-Yves Chibon e1497f
    +---------------+---------+--------------+-----------------------------+
Lei Yang 566c51
Lei Yang 566c51
    Sample response
Lei Yang 566c51
    ^^^^^^^^^^^^^^^
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
    ::
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
        {
Pierre-Yves Chibon c27d61
          "flag": {
Pierre-Yves Chibon c27d61
            "comment": "Tests failed",
Pierre-Yves Chibon c27d61
            "date_created": "1510742565",
Pierre-Yves Chibon c27d61
            "percent": 0,
Pierre-Yves Chibon c27d61
            "pull_request_uid": "62b49f00d489452994de5010565fab81",
Pierre-Yves Chibon abcbf7
            "status": "error",
Pierre-Yves Chibon c27d61
            "url": "http://jenkins.cloud.fedoraproject.org/",
Pierre-Yves Chibon c27d61
            "user": {
Pierre-Yves Chibon c27d61
              "default_email": "bar@pingou.com",
Pierre-Yves Chibon c27d61
              "emails": ["bar@pingou.com", "foo@pingou.com"],
Pierre-Yves Chibon c27d61
              "fullname": "PY C",
Pierre-Yves Chibon c27d61
              "name": "pingou"},
Pierre-Yves Chibon c27d61
            "username": "Jenkins"},
Pierre-Yves Chibon c27d61
          "message": u"Flag added",
Pierre-Yves Chibon c27d61
          "uid": u"jenkins_build_pagure_100+seed"
Pierre-Yves Chibon e39f18
        }
Pierre-Yves Chibon e39f18
Lei Yang 566c51
    ::
Lei Yang 566c51
Lei Yang 566c51
        {
Pierre-Yves Chibon c27d61
          "flag": {
Pierre-Yves Chibon c27d61
            "comment": "Tests failed",
Pierre-Yves Chibon c27d61
            "date_created": "1510742565",
Pierre-Yves Chibon c27d61
            "percent": 0,
Pierre-Yves Chibon c27d61
            "pull_request_uid": "62b49f00d489452994de5010565fab81",
Pierre-Yves Chibon abcbf7
            "status": "error",
Pierre-Yves Chibon c27d61
            "url": "http://jenkins.cloud.fedoraproject.org/",
Pierre-Yves Chibon c27d61
            "user": {
Pierre-Yves Chibon c27d61
              "default_email": "bar@pingou.com",
Pierre-Yves Chibon c27d61
              "emails": ["bar@pingou.com", "foo@pingou.com"],
Pierre-Yves Chibon c27d61
              "fullname": "PY C",
Pierre-Yves Chibon c27d61
              "name": "pingou"},
Pierre-Yves Chibon c27d61
            "username": "Jenkins"},
Pierre-Yves Chibon c27d61
          "message": u"Flag updated",
Pierre-Yves Chibon c27d61
          "uid": u"jenkins_build_pagure_100+seed"
Lei Yang 566c51
        }
Lei Yang 566c51
Pierre-Yves Chibon 4768f2
    """  # noqa
Patrick Uiterwijk eabc8e
    repo = get_authorized_api_project(
Pierre-Yves Chibon b130e5
        flask.g.session, repo, user=username, namespace=namespace)
farhaanbukhsh 44a97a
Pierre-Yves Chibon e39f18
    output = {}
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
    if repo is None:
Pierre-Yves Chibon 1dfd94
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 1dfd94
            404, error_code=APIERROR.ENOPROJECT)
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
    if not repo.settings.get('pull_requests', True):
Pierre-Yves Chibon e39f18
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon e39f18
            404, error_code=APIERROR.EPULLREQUESTSDISABLED)
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon 1dfd94
    if flask.g.token.project and repo != flask.g.token.project:
Pierre-Yves Chibon 1dfd94
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 1dfd94
            401, error_code=APIERROR.EINVALIDTOK)
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
    request = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
        flask.g.session, project_id=repo.id, requestid=requestid)
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
    if not request:
Pierre-Yves Chibon e39f18
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOREQ)
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon abcbf7
    if 'status' in flask.request.form:
Pierre-Yves Chibon abcbf7
        form = pagure.forms.AddPullRequestFlagForm(csrf_enabled=False)
Pierre-Yves Chibon abcbf7
    else:
Pierre-Yves Chibon abcbf7
        form = pagure.forms.AddPullRequestFlagFormV1(csrf_enabled=False)
Pierre-Yves Chibon e39f18
    if form.validate_on_submit():
Pierre-Yves Chibon e39f18
        username = form.username.data
Pierre-Yves Chibon abcbf7
        percent = form.percent.data.strip() or None
Pierre-Yves Chibon e39f18
        comment = form.comment.data.strip()
Pierre-Yves Chibon e39f18
        url = form.url.data.strip()
Pierre-Yves Chibon e39f18
        uid = form.uid.data.strip() if form.uid.data else None
Pierre-Yves Chibon abcbf7
        if 'status' in flask.request.form:
Pierre-Yves Chibon abcbf7
            status = form.status.data.strip()
Pierre-Yves Chibon abcbf7
        else:
Pierre-Yves Chibon abcbf7
            if percent is None:
Pierre-Yves Chibon abcbf7
                status = 'pending'
Pierre-Yves Chibon abcbf7
            else:
Pierre-Yves Chibon abcbf7
                status = 'success' if percent != '0' else 'failure'
Pierre-Yves Chibon e39f18
        try:
Pierre-Yves Chibon e39f18
            # New Flag
Pierre-Yves Chibon c27d61
            message, uid = pagure.lib.add_pull_request_flag(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon e39f18
                request=request,
Pierre-Yves Chibon e39f18
                username=username,
Pierre-Yves Chibon abcbf7
                status=status,
Pierre-Yves Chibon e39f18
                percent=percent,
Pierre-Yves Chibon e39f18
                comment=comment,
Pierre-Yves Chibon e39f18
                url=url,
Pierre-Yves Chibon e39f18
                uid=uid,
Pierre-Yves Chibon e39f18
                user=flask.g.fas_user.username,
Pierre-Yves Chibon ba2b1c
                token=flask.g.token.id,
Pierre-Yves Chibon b130e5
                requestfolder=pagure_config['REQUESTS_FOLDER'],
Pierre-Yves Chibon e39f18
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon dc4c19
            pr_flag = pagure.lib.get_pull_request_flag_by_uid(
Pierre-Yves Chibon b130e5
                flask.g.session, request, uid)
Pierre-Yves Chibon e39f18
            output['message'] = message
Pierre-Yves Chibon c27d61
            output['uid'] = uid
Pierre-Yves Chibon c27d61
            output['flag'] = pr_flag.to_json()
Pierre-Yves Chibon e39f18
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon e39f18
            raise pagure.exceptions.APIError(
Pierre-Yves Chibon e39f18
                400, error_code=APIERROR.ENOCODE, error=str(err))
Pierre-Yves Chibon fa97f7
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            _log.exception(err)
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon e39f18
            raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
    else:
Pierre-Yves Chibon f7fcaa
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon f7fcaa
            400, error_code=APIERROR.EINVALIDREQ, errors=form.errors)
Pierre-Yves Chibon e39f18
Pierre-Yves Chibon e39f18
    jsonout = flask.jsonify(output)
Pierre-Yves Chibon e39f18
    return jsonout
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
@API.route(
Pierre-Yves Chibon 4f5301
    '/<repo>/pull-request/<int:requestid>/subscribe',</int:requestid></repo>
Pierre-Yves Chibon 4f5301
    methods=['POST'])
Pierre-Yves Chibon 4f5301
@API.route(
Pierre-Yves Chibon 4f5301
    '/<namespace>/<repo>/pull-request/<int:requestid>/subscribe',</int:requestid></repo></namespace>
Pierre-Yves Chibon 4f5301
    methods=['POST'])
Pierre-Yves Chibon 4f5301
@API.route(
Pierre-Yves Chibon 4f5301
    '/fork/<username>/<repo>/pull-request/<int:requestid>/subscribe',</int:requestid></repo></username>
Pierre-Yves Chibon 4f5301
    methods=['POST'])
Pierre-Yves Chibon 4f5301
@API.route(
Pierre-Yves Chibon f21b8c
    '/fork/<username>/<namespace>/<repo>/pull-request/<int:requestid>'</int:requestid></repo></namespace></username>
Pierre-Yves Chibon f21b8c
    '/subscribe', methods=['POST'])
Pierre-Yves Chibon 690101
@api_login_required(acls=['pull_request_subscribe'])
Pierre-Yves Chibon 4f5301
@api_method
Pierre-Yves Chibon f21b8c
def api_subscribe_pull_request(
Pierre-Yves Chibon f21b8c
        repo, requestid, username=None, namespace=None):
Pierre-Yves Chibon 4f5301
    """
Pierre-Yves Chibon 4f5301
    Subscribe to an pull-request
Pierre-Yves Chibon 4f5301
    ----------------------------
Pierre-Yves Chibon 4f5301
    Allows someone to subscribe to or unsubscribe from the notifications
Pierre-Yves Chibon 4f5301
    related to a pull-request.
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    ::
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
        POST /api/0/<repo>/pull-request/<request id="">/subscribe</request></repo>
Pierre-Yves Chibon 4f5301
        POST /api/0/<namespace>/<repo>/pull-request/<request id="">/subscribe</request></repo></namespace>
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    ::
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
        POST /api/0/fork/<username>/<repo>/pull-request/<request id="">/subscribe</request></repo></username>
Pierre-Yves Chibon 4f5301
        POST /api/0/fork/<username>/<namespace>/<repo>/pull-request/<request id="">/subscribe</request></repo></namespace></username>
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    Input
Pierre-Yves Chibon 4f5301
    ^^^^^
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    +--------------+----------+---------------+---------------------------+
Pierre-Yves Chibon 4f5301
    | Key          | Type     | Optionality   | Description               |
Pierre-Yves Chibon 4f5301
    +==============+==========+===============+===========================+
Pierre-Yves Chibon 4f5301
    | ``status``   | boolean  | Mandatory     | The intended subscription |
Pierre-Yves Chibon 4f5301
    |              |          |               | status. ``true`` for      |
Pierre-Yves Chibon 4f5301
    |              |          |               | subscribing, ``false``    |
Pierre-Yves Chibon 4f5301
    |              |          |               | for unsubscribing.        |
Pierre-Yves Chibon 4f5301
    +--------------+----------+---------------+---------------------------+
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    Sample response
Pierre-Yves Chibon 4f5301
    ^^^^^^^^^^^^^^^
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    ::
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
        {
Pierre-Yves Chibon 4f5301
          "message": "User subscribed"
Pierre-Yves Chibon 4f5301
        }
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    """  # noqa
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    repo = get_authorized_api_project(
Pierre-Yves Chibon b130e5
        flask.g.session, repo, user=username, namespace=namespace)
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    output = {}
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    if repo is None:
Pierre-Yves Chibon 4f5301
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 4f5301
            404, error_code=APIERROR.ENOPROJECT)
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    if not repo.settings.get('pull_requests', True):
Pierre-Yves Chibon 4f5301
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 4f5301
            404, error_code=APIERROR.EPULLREQUESTSDISABLED)
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    if api_authenticated():
Pierre-Yves Chibon 4f5301
        if flask.g.token.project and repo != flask.g.token.project:
Pierre-Yves Chibon 4f5301
            raise pagure.exceptions.APIError(
Pierre-Yves Chibon 4f5301
                401, error_code=APIERROR.EINVALIDTOK)
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    request = pagure.lib.search_pull_requests(
Pierre-Yves Chibon b130e5
        flask.g.session, project_id=repo.id, requestid=requestid)
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    if not request:
Pierre-Yves Chibon 4f5301
        raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOREQ)
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    form = pagure.forms.SubscribtionForm(csrf_enabled=False)
Pierre-Yves Chibon 4f5301
    if form.validate_on_submit():
Pierre-Yves Chibon 4f5301
        status = str(form.status.data).strip().lower() in ['1', 'true']
Pierre-Yves Chibon 4f5301
        try:
Pierre-Yves Chibon 4f5301
            # Toggle subscribtion
Pierre-Yves Chibon 4f5301
            message = pagure.lib.set_watch_obj(
Pierre-Yves Chibon b130e5
                flask.g.session,
Pierre-Yves Chibon 4f5301
                user=flask.g.fas_user.username,
Pierre-Yves Chibon 4f5301
                obj=request,
Pierre-Yves Chibon 4f5301
                watch_status=status
Pierre-Yves Chibon 4f5301
            )
Pierre-Yves Chibon b130e5
            flask.g.session.commit()
Pierre-Yves Chibon 4f5301
            output['message'] = message
Pierre-Yves Chibon 4f5301
        except SQLAlchemyError as err:  # pragma: no cover
Pierre-Yves Chibon b130e5
            flask.g.session.rollback()
Pierre-Yves Chibon b130e5
            _log.logger.exception(err)
Pierre-Yves Chibon 4f5301
            raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    else:
Pierre-Yves Chibon 4f5301
        raise pagure.exceptions.APIError(
Pierre-Yves Chibon 4f5301
            400, error_code=APIERROR.EINVALIDREQ, errors=form.errors)
Pierre-Yves Chibon 4f5301
Pierre-Yves Chibon 4f5301
    jsonout = flask.jsonify(output)
Pierre-Yves Chibon 4f5301
    return jsonout