Blame pagure/lib/tasks.py

Patrick Uiterwijk 0f077b
# -*- coding: utf-8 -*-
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 0f077b
"""
Patrick Uiterwijk 0f077b
 (c) 2017 - Copyright Red Hat Inc
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 0f077b
 Authors:
Patrick Uiterwijk 0f077b
   Patrick Uiterwijk <puiterwijk@redhat.com></puiterwijk@redhat.com>
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 0f077b
"""
Patrick Uiterwijk 0f077b
Pierre-Yves Chibon 67d1cc
from __future__ import unicode_literals, absolute_import
Aurélien Bompard 831553
Pierre-Yves Chibon 716362
import collections
Pierre-Yves Chibon 1828a2
import datetime
Pierre-Yves Chibon 36309a
import hashlib
Patrick Uiterwijk 4e3dbd
import os
Patrick Uiterwijk 4e3dbd
import os.path
Patrick Uiterwijk 4e3dbd
import shutil
Patrick Uiterwijk 3f97f6
import subprocess
Patrick Uiterwijk 7b9080
import time
Patrick Uiterwijk 4e3dbd
Pierre-Yves Chibon 1828a2
import arrow
Patrick Uiterwijk 4e3dbd
import pygit2
Patrick Uiterwijk 4e3dbd
import six
Patrick Uiterwijk 4e3dbd
Pierre-Yves Chibon c2199b
from celery import Celery
Pierre-Yves Chibon c2199b
from celery.result import AsyncResult
Pierre-Yves Chibon 24747e
from celery.signals import after_setup_task_logger
Pierre-Yves Chibon 24747e
from celery.utils.log import get_task_logger
Vivek Anand ed7e6e
from sqlalchemy.exc import SQLAlchemyError
Vivek Anand ed7e6e
Patrick Uiterwijk 4e3dbd
import pagure.lib.git
Pierre-Yves Chibon 145998
import pagure.lib.git_auth
Pierre-Yves Chibon 11d019
import pagure.lib.link
Pierre-Yves Chibon 930073
import pagure.lib.query
Pierre-Yves Chibon 2479ca
import pagure.lib.model
Patrick Uiterwijk 04c084
import pagure.lib.repo
Pierre-Yves Chibon b130e5
import pagure.utils
Pierre-Yves Chibon 1aac43
from pagure.lib.tasks_utils import pagure_task
Pierre-Yves Chibon b130e5
from pagure.config import config as pagure_config
Pierre-Yves Chibon 11d019
from pagure.utils import get_parent_repo_path
Patrick Uiterwijk 0f077b
Pierre-Yves Chibon b130e5
# logging.config.dictConfig(pagure_config.get('LOGGING') or {'version': 1})
Pierre-Yves Chibon 24747e
_log = get_task_logger(__name__)
Patrick Uiterwijk 96c928
Patrick Uiterwijk 0f077b
Pierre-Yves Chibon 9c2953
if os.environ.get("PAGURE_BROKER_URL"):
Pierre-Yves Chibon 9c2953
    broker_url = os.environ["PAGURE_BROKER_URL"]
Pierre-Yves Chibon 9c2953
elif pagure_config.get("BROKER_URL"):
Pierre-Yves Chibon 9c2953
    broker_url = pagure_config["BROKER_URL"]
Patrick Uiterwijk 55e7e0
else:
Pierre-Yves Chibon 9c2953
    broker_url = "redis://%s" % pagure_config["REDIS_HOST"]
Patrick Uiterwijk 55e7e0
Pierre-Yves Chibon 9c2953
conn = Celery("tasks", broker=broker_url, backend=broker_url)
Pierre-Yves Chibon 9c2953
conn.conf.update(pagure_config["CELERY_CONFIG"])
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 0f077b
Pierre-Yves Chibon 24747e
@after_setup_task_logger.connect
Pierre-Yves Chibon 24747e
def augment_celery_log(**kwargs):
Pierre-Yves Chibon 24747e
    pagure.utils.set_up_logging(force=True)
Pierre-Yves Chibon 24747e
Pierre-Yves Chibon 24747e
Patrick Uiterwijk 0f077b
def get_result(uuid):
Pierre-Yves Chibon 274e60
    """ Returns the AsyncResult object for a given task.
Pierre-Yves Chibon 274e60
Pierre-Yves Chibon 274e60
    :arg uuid: the unique identifier of the task to retrieve.
Pierre-Yves Chibon 274e60
    :type uuid: str
Pierre-Yves Chibon 274e60
    :return: celery.result.AsyncResult
Pierre-Yves Chibon 274e60
Pierre-Yves Chibon 274e60
    """
Patrick Uiterwijk 0f077b
    return AsyncResult(uuid, conn.backend)
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 0f077b
def ret(endpoint, **kwargs):
Pierre-Yves Chibon 9c2953
    toret = {"endpoint": endpoint}
Patrick Uiterwijk 0f077b
    toret.update(kwargs)
Patrick Uiterwijk 0f077b
    return toret
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 0f077b
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("GITOLITE_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Pierre-Yves Chibon 5f2c51
def generate_gitolite_acls(
Pierre-Yves Chibon 9c2953
    self, session, namespace=None, name=None, user=None, group=None
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 274e60
    """ Generate the gitolite configuration file either entirely or for a
Pierre-Yves Chibon 274e60
    specific project.
Pierre-Yves Chibon 274e60
Slavek Kabrda efeaa6
    :arg session: SQLAlchemy session object
Slavek Kabrda efeaa6
    :type session: sqlalchemy.orm.session.Session
Pierre-Yves Chibon 274e60
    :kwarg namespace: the namespace of the project
Pierre-Yves Chibon ccb160
    :type namespace: None or str
Pierre-Yves Chibon 274e60
    :kwarg name: the name of the project
Pierre-Yves Chibon ccb160
    :type name: None or str
Pierre-Yves Chibon 274e60
    :kwarg user: the user of the project, only set if the project is a fork
Pierre-Yves Chibon ccb160
    :type user: None or str
Pierre-Yves Chibon ccb160
    :kwarg group: the group to refresh the members of
Pierre-Yves Chibon ccb160
    :type group: None or str
Pierre-Yves Chibon 274e60
Pierre-Yves Chibon 274e60
    """
Pierre-Yves Chibon 274e60
    project = None
Pierre-Yves Chibon 274e60
    if name and name != -1:
Pierre-Yves Chibon 930073
        project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
            session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 274e60
    elif name == -1:
Pierre-Yves Chibon 274e60
        project = name
Patrick Uiterwijk ad0b72
    helper = pagure.lib.git_auth.get_git_auth_helper()
Pierre-Yves Chibon 9c2953
    _log.debug("Got helper: %s", helper)
Pierre-Yves Chibon ccb160
Pierre-Yves Chibon d012ee
    group_obj = None
Pierre-Yves Chibon d012ee
    if group:
Pierre-Yves Chibon 930073
        group_obj = pagure.lib.query.search_groups(session, group_name=group)
Pierre-Yves Chibon ccb160
    _log.debug(
Pierre-Yves Chibon 9c2953
        "Calling helper: %s with arg: project=%s, group=%s",
Pierre-Yves Chibon 9c2953
        helper,
Pierre-Yves Chibon 9c2953
        project,
Pierre-Yves Chibon 9c2953
        group_obj,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon ccb160
    helper.generate_acls(project=project, group=group_obj)
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 930073
    pagure.lib.query.update_read_only_mode(session, project, read_only=False)
Vivek Anand ed7e6e
    try:
Vivek Anand ed7e6e
        session.commit()
Pierre-Yves Chibon 9c2953
        _log.debug("Project %s is no longer in Read Only Mode", project)
Vivek Anand ed7e6e
    except SQLAlchemyError:
Vivek Anand ed7e6e
        session.rollback()
Pierre-Yves Chibon 9c2953
        _log.exception("Failed to unmark read_only for: %s project", project)
Patrick Uiterwijk 0f077b
Patrick Uiterwijk 0f077b
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("GITOLITE_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda 5ab53d
def gitolite_post_compile_only(self, session):
Slavek Kabrda 5ab53d
    """ Do gitolite post-processing only. Most importantly, this processes SSH
Slavek Kabrda 5ab53d
    keys used by gitolite. This is an optimization task that's supposed to be
Slavek Kabrda 5ab53d
    used if you only need to run `gitolite trigger POST_COMPILE` without
Slavek Kabrda 5ab53d
    touching any other gitolite configuration
Slavek Kabrda 5ab53d
    """
Patrick Uiterwijk ad0b72
    helper = pagure.lib.git_auth.get_git_auth_helper()
Pierre-Yves Chibon 9c2953
    _log.debug("Got helper: %s", helper)
Pierre-Yves Chibon 9c2953
    if hasattr(helper, "post_compile_only"):
Slavek Kabrda 5ab53d
        helper.post_compile_only()
Slavek Kabrda 5ab53d
    else:
Slavek Kabrda 5ab53d
        helper.generate_acls(project=None)
Slavek Kabrda 5ab53d
Slavek Kabrda 5ab53d
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("GITOLITE_CELERY_QUEUE", None), bind=True)
Slavek Kabrda 5ab53d
@pagure_task
Pierre-Yves Chibon 5f2c51
def delete_project(
Pierre-Yves Chibon 9c2953
    self, session, namespace=None, name=None, user=None, action_user=None
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 5b06f7
    """ Delete a project in pagure.
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 5b06f7
    This is achieved in three steps:
Pierre-Yves Chibon 5b06f7
    - Remove the project from gitolite.conf
Pierre-Yves Chibon 5b06f7
    - Remove the git repositories on disk
Pierre-Yves Chibon 5b06f7
    - Remove the project from the DB
Pierre-Yves Chibon 5b06f7
Slavek Kabrda efeaa6
    :arg session: SQLAlchemy session object
Slavek Kabrda efeaa6
    :type session: sqlalchemy.orm.session.Session
Pierre-Yves Chibon 5b06f7
    :kwarg namespace: the namespace of the project
Pierre-Yves Chibon 5b06f7
    :type namespace: None or str
Pierre-Yves Chibon 5b06f7
    :kwarg name: the name of the project
Pierre-Yves Chibon 5b06f7
    :type name: None or str
Pierre-Yves Chibon 5b06f7
    :kwarg user: the user of the project, only set if the project is a fork
Pierre-Yves Chibon 5b06f7
    :type user: None or str
Shaily b11790
    :kwarg action_user: the user deleting the project
Shaily b11790
    :type action_user: None or str
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 5b06f7
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 5b06f7
    if not project:
Pierre-Yves Chibon 5b06f7
        raise RuntimeError(
Pierre-Yves Chibon 9c2953
            "Project: %s/%s from user: %s not found in the DB"
Pierre-Yves Chibon 9c2953
            % (namespace, name, user)
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 5b06f7
    # Remove the project from gitolite.conf
Patrick Uiterwijk ad0b72
    helper = pagure.lib.git_auth.get_git_auth_helper()
Pierre-Yves Chibon 9c2953
    _log.debug("Got helper: %s", helper)
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 5b06f7
    _log.debug(
Pierre-Yves Chibon 9c2953
        "Calling helper: %s with arg: project=%s", helper, project.fullname
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 5b06f7
    helper.remove_acls(session=session, project=project)
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 5b06f7
    # Remove the git repositories on disk
Patrick Uiterwijk 3f97f6
    pagure.lib.git.delete_project_repos(project)
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 5b06f7
    # Remove the project from the DB
Pierre-Yves Chibon 5b06f7
    username = project.user.user
Pierre-Yves Chibon 5b06f7
    try:
Pierre-Yves Chibon 818658
        project_json = project.to_json(public=True)
Pierre-Yves Chibon 5b06f7
        session.delete(project)
Pierre-Yves Chibon 5b06f7
        session.commit()
Shaily b11790
        pagure.lib.notify.log(
Shaily b11790
            project,
Pierre-Yves Chibon 9c2953
            topic="project.deleted",
Pierre-Yves Chibon 9c2953
            msg=dict(project=project_json, agent=action_user),
Shaily b11790
        )
Pierre-Yves Chibon 5b06f7
    except SQLAlchemyError:
Pierre-Yves Chibon 5b06f7
        session.rollback()
Pierre-Yves Chibon 5b06f7
        _log.exception(
Pierre-Yves Chibon 9c2953
            "Failed to delete project: %s from the DB", project.fullname
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 9c2953
    return ret("ui_ns.view_user", username=username)
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 5b06f7
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Pierre-Yves Chibon 9c2953
def create_project(
Pierre-Yves Chibon 9c2953
    self, session, username, namespace, name, add_readme, ignore_existing_repo
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 274e60
    """ Create a project.
Pierre-Yves Chibon 274e60
Slavek Kabrda efeaa6
    :arg session: SQLAlchemy session object
Slavek Kabrda efeaa6
    :type session: sqlalchemy.orm.session.Session
Pierre-Yves Chibon 274e60
    :kwarg username: the user creating the project
Pierre-Yves Chibon 274e60
    :type user: str
Pierre-Yves Chibon 274e60
    :kwarg namespace: the namespace of the project
Pierre-Yves Chibon 274e60
    :type namespace: str
Pierre-Yves Chibon 274e60
    :kwarg name: the name of the project
Pierre-Yves Chibon 274e60
    :type name: str
Pierre-Yves Chibon 274e60
    :kwarg add_readme: a boolean specifying if the project should be
Pierre-Yves Chibon 274e60
        created with a README file or not
Pierre-Yves Chibon 274e60
    :type add_readme: bool
Pierre-Yves Chibon 274e60
    :kwarg ignore_existing_repo: a boolean specifying whether the creation
Pierre-Yves Chibon 274e60
        of the project should fail if the repo exists on disk or not
Pierre-Yves Chibon 274e60
    :type ignore_existing_repo: bool
Pierre-Yves Chibon 274e60
Pierre-Yves Chibon 274e60
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 930073
        session, namespace=namespace, name=name
Pierre-Yves Chibon 930073
    )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 930073
    userobj = pagure.lib.query.search_user(session, username=username)
Patrick Uiterwijk 7b9080
Pierre-Yves Chibon 6c716f
    # Add the readme file if it was asked
Pierre-Yves Chibon 6c716f
    templ = None
Pierre-Yves Chibon 6c716f
    if project.is_fork:
Pierre-Yves Chibon 6c716f
        templ = pagure_config.get("FORK_TEMPLATE_PATH")
Pierre-Yves Chibon 6c716f
    else:
Pierre-Yves Chibon 6c716f
        templ = pagure_config.get("PROJECT_TEMPLATE_PATH")
Pierre-Yves Chibon 6c716f
    if templ:
Pierre-Yves Chibon 6c716f
        if not os.path.exists(templ):
Pierre-Yves Chibon 6c716f
            _log.warning(
Pierre-Yves Chibon 114311
                "Invalid git template configured: %s, not found on disk", templ
Pierre-Yves Chibon 6c716f
            )
Pierre-Yves Chibon 6c716f
            templ = None
Patrick Uiterwijk 7b9080
        else:
Pierre-Yves Chibon 6c716f
            _log.debug("  Using template at: %s", templ)
Pierre-Yves Chibon 75a89d
Pierre-Yves Chibon 7834b6
    # There is a risk for a race-condition here between when the repo is
Pierre-Yves Chibon 7834b6
    # created and when the README gets added. However, this risk is small
Pierre-Yves Chibon 7834b6
    # enough that we will keep this as is for now (esp since it fixes the
Pierre-Yves Chibon 7834b6
    # situation where deleting the project raised an error if it was in the
Pierre-Yves Chibon 7834b6
    # middle of the lock)
Pierre-Yves Chibon 6c716f
    try:
Pierre-Yves Chibon 6c716f
        with project.lock("WORKER"):
Patrick Uiterwijk 6876a8
            pagure.lib.git.create_project_repos(
Patrick Uiterwijk 6876a8
                project,
Patrick Uiterwijk 6876a8
                project.repospanner_region,
Patrick Uiterwijk 6876a8
                templ,
Patrick Uiterwijk 6876a8
                ignore_existing_repo,
Patrick Uiterwijk 6876a8
            )
Pierre-Yves Chibon 15a664
    except Exception:
Pierre-Yves Chibon 6c716f
        session.delete(project)
Pierre-Yves Chibon 6c716f
        session.commit()
Pierre-Yves Chibon 6c716f
        raise
Pierre-Yves Chibon 42df12
Pierre-Yves Chibon 6c716f
    if add_readme:
Pierre-Yves Chibon 6c716f
        with project.lock("WORKER"):
Patrick Uiterwijk 3f97f6
            with pagure.lib.git.TemporaryClone(
Patrick Uiterwijk 3f97f6
                project, "main", "add_readme"
Patrick Uiterwijk 3f97f6
            ) as tempclone:
Patrick Uiterwijk 3f97f6
                temp_gitrepo = tempclone.repo
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
                # Add README file
Patrick Uiterwijk 3f97f6
                author = userobj.fullname or userobj.user
Patrick Uiterwijk 3f97f6
                author_email = userobj.default_email
Patrick Uiterwijk 3f97f6
                if six.PY2:
Patrick Uiterwijk 3f97f6
                    author = author.encode("utf-8")
Patrick Uiterwijk 3f97f6
                    author_email = author_email.encode("utf-8")
Patrick Uiterwijk 3f97f6
                author = pygit2.Signature(author, author_email)
Patrick Uiterwijk 3f97f6
                content = "# %s\n\n%s" % (name, project.description)
Patrick Uiterwijk 3f97f6
                readme_file = os.path.join(temp_gitrepo.workdir, "README.md")
Patrick Uiterwijk 3f97f6
                with open(readme_file, "wb") as stream:
Patrick Uiterwijk 3f97f6
                    stream.write(content.encode("utf-8"))
Patrick Uiterwijk 3f97f6
                temp_gitrepo.index.add_all()
Patrick Uiterwijk 3f97f6
                temp_gitrepo.index.write()
Patrick Uiterwijk 3f97f6
                tree = temp_gitrepo.index.write_tree()
Patrick Uiterwijk 3f97f6
                temp_gitrepo.create_commit(
Patrick Uiterwijk 3f97f6
                    "HEAD", author, author, "Added the README", tree, []
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 42df12
Patrick Uiterwijk 3f97f6
                master_ref = temp_gitrepo.lookup_reference("HEAD").resolve()
Patrick Uiterwijk 03a519
                tempclone.push("pagure", master_ref.name, internal="yes")
Patrick Uiterwijk 7b9080
Pierre-Yves Chibon 56e29f
    task = generate_gitolite_acls.delay(
Pierre-Yves Chibon 274e60
        namespace=project.namespace,
Pierre-Yves Chibon 274e60
        name=project.name,
Pierre-Yves Chibon 9c2953
        user=project.user.user if project.is_fork else None,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 9c2953
    _log.info("Refreshing gitolite config queued in task: %s", task.id)
Pierre-Yves Chibon 274e60
Pierre-Yves Chibon 9c2953
    return ret("ui_ns.view_repo", repo=name, namespace=namespace)
Patrick Uiterwijk 8e1ee6
Patrick Uiterwijk 8e1ee6
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("SLOW_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Pierre-Yves Chibon 9c2953
def update_git(
Pierre-Yves Chibon 9c2953
    self, session, name, namespace, user, ticketuid=None, requestuid=None
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 314da3
    """ Update the JSON representation of either a ticket or a pull-request
Pierre-Yves Chibon 314da3
    depending on the argument specified.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 9c2953
    project_lock = "WORKER"
Pierre-Yves Chibon 09776e
    if ticketuid is not None:
Pierre-Yves Chibon 9c2953
        project_lock = "WORKER_TICKET"
Pierre-Yves Chibon 09776e
    elif requestuid is not None:
Pierre-Yves Chibon 9c2953
        project_lock = "WORKER_REQUEST"
Pierre-Yves Chibon 09776e
Pierre-Yves Chibon 09776e
    with project.lock(project_lock):
Patrick Uiterwijk 7b9080
        if ticketuid is not None:
Pierre-Yves Chibon 930073
            obj = pagure.lib.query.get_issue_by_uid(session, ticketuid)
Patrick Uiterwijk 7b9080
        elif requestuid is not None:
Pierre-Yves Chibon 930073
            obj = pagure.lib.query.get_request_by_uid(session, requestuid)
Patrick Uiterwijk 7b9080
        else:
Pierre-Yves Chibon 9c2953
            raise NotImplementedError("No ticket ID or request ID provided")
Patrick Uiterwijk 7b9080
Patrick Uiterwijk 7b9080
        if obj is None:
Pierre-Yves Chibon 9c2953
            raise Exception("Unable to find object")
Patrick Uiterwijk 7b9080
Patrick Uiterwijk 3f97f6
        result = pagure.lib.git._update_git(obj, project)
Patrick Uiterwijk 8e1ee6
Patrick Uiterwijk 120396
    return result
Patrick Uiterwijk 189fa8
Patrick Uiterwijk 189fa8
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("SLOW_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Patrick Uiterwijk 3f97f6
def clean_git(self, session, name, namespace, user, obj_repotype, obj_uid):
Pierre-Yves Chibon 314da3
    """ Remove the JSON representation of a ticket on the git repository
Pierre-Yves Chibon 314da3
    for tickets.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 9c2953
    with project.lock("WORKER_TICKET"):
Patrick Uiterwijk 3f97f6
        result = pagure.lib.git._clean_git(project, obj_repotype, obj_uid)
Patrick Uiterwijk 189fa8
Patrick Uiterwijk 189fa8
    return result
Patrick Uiterwijk 8cb224
Patrick Uiterwijk 8cb224
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Pierre-Yves Chibon 9c2953
def update_file_in_git(
Pierre-Yves Chibon 9c2953
    self,
Pierre-Yves Chibon 9c2953
    session,
Pierre-Yves Chibon 9c2953
    name,
Pierre-Yves Chibon 9c2953
    namespace,
Pierre-Yves Chibon 9c2953
    user,
Pierre-Yves Chibon 9c2953
    branch,
Pierre-Yves Chibon 9c2953
    branchto,
Pierre-Yves Chibon 9c2953
    filename,
Pierre-Yves Chibon 9c2953
    content,
Pierre-Yves Chibon 9c2953
    message,
Pierre-Yves Chibon 9c2953
    username,
Pierre-Yves Chibon 9c2953
    email,
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 314da3
    """ Update a file in the specified git repo.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon 930073
    userobj = pagure.lib.query.search_user(session, username=username)
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 8cb224
Pierre-Yves Chibon 9c2953
    with project.lock("WORKER"):
Pierre-Yves Chibon 715218
        pagure.lib.git._update_file_in_git(
Pierre-Yves Chibon 9c2953
            project,
Pierre-Yves Chibon 9c2953
            branch,
Pierre-Yves Chibon 9c2953
            branchto,
Pierre-Yves Chibon 9c2953
            filename,
Pierre-Yves Chibon 9c2953
            content,
Pierre-Yves Chibon 9c2953
            message,
Pierre-Yves Chibon 9c2953
            userobj,
Pierre-Yves Chibon 9c2953
            email,
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk 8cb224
Pierre-Yves Chibon 9c2953
    return ret(
Pierre-Yves Chibon 9c2953
        "ui_ns.view_commits",
Pierre-Yves Chibon 9c2953
        repo=project.name,
Pierre-Yves Chibon 9c2953
        username=user,
Pierre-Yves Chibon 9c2953
        namespace=namespace,
Pierre-Yves Chibon 9c2953
        branchname=branchto,
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 8cb224
Patrick Uiterwijk 8cb224
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda efeaa6
def delete_branch(self, session, name, namespace, user, branchname):
Pierre-Yves Chibon 314da3
    """ Delete a branch from a git repo.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 9c2953
    with project.lock("WORKER"):
Pierre-Yves Chibon 9c2953
        repo_obj = pygit2.Repository(pagure.utils.get_repo_path(project))
Patrick Uiterwijk 8cb224
Patrick Uiterwijk 7b9080
        try:
Patrick Uiterwijk 7b9080
            branch = repo_obj.lookup_branch(branchname)
Patrick Uiterwijk 7b9080
            branch.delete()
Patrick Uiterwijk 7b9080
        except pygit2.GitError as err:
Patrick Uiterwijk 7b9080
            _log.exception(err)
Patrick Uiterwijk 8cb224
Pierre-Yves Chibon b130e5
    return ret(
Ryan Lerch 2867e2
        "ui_ns.view_branches", repo=name, namespace=namespace, username=user
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk ac056b
Patrick Uiterwijk ac056b
Pierre-Yves Chibon 974201
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Pierre-Yves Chibon 9c2953
def fork(
Pierre-Yves Chibon 9c2953
    self,
Pierre-Yves Chibon 9c2953
    session,
Pierre-Yves Chibon 9c2953
    name,
Pierre-Yves Chibon 9c2953
    namespace,
Pierre-Yves Chibon 9c2953
    user_owner,
Pierre-Yves Chibon 9c2953
    user_forker,
Pierre-Yves Chibon 9c2953
    editbranch,
Pierre-Yves Chibon 9c2953
    editfile,
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 274e60
    """ Forks the specified project for the specified user.
Pierre-Yves Chibon 274e60
Pierre-Yves Chibon 274e60
    :arg namespace: the namespace of the project
Pierre-Yves Chibon 274e60
    :type namespace: str
Pierre-Yves Chibon 274e60
    :arg name: the name of the project
Pierre-Yves Chibon 274e60
    :type name: str
Pierre-Yves Chibon 274e60
    :arg user_owner: the user of which the project is forked, only set
Pierre-Yves Chibon 274e60
        if the project is already a fork
Pierre-Yves Chibon 274e60
    :type user_owner: str
Pierre-Yves Chibon 274e60
    :arg user_forker: the user forking the project
Pierre-Yves Chibon 274e60
    :type user_forker: str
Pierre-Yves Chibon 274e60
    :kwarg editbranch: the name of the branch in which the user asked to
Pierre-Yves Chibon 274e60
        edit a file
Pierre-Yves Chibon 274e60
    :type editbranch: str
Pierre-Yves Chibon 274e60
    :kwarg editfile: the file the user asked to edit
Pierre-Yves Chibon 274e60
    :type editfile: str
Pierre-Yves Chibon 274e60
Pierre-Yves Chibon 274e60
    """
Pierre-Yves Chibon 930073
    repo_from = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user_owner
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 930073
    repo_to = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user_forker
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 7b9080
Pierre-Yves Chibon 9c2953
    with repo_to.lock("WORKER"):
Patrick Uiterwijk 3f97f6
        pagure.lib.git.create_project_repos(
Patrick Uiterwijk 3f97f6
            repo_to, repo_to.repospanner_region, None, False
Patrick Uiterwijk 3f97f6
        )
Patrick Uiterwijk 7b9080
Patrick Uiterwijk 3f97f6
        with pagure.lib.git.TemporaryClone(
Slavek Kabrda 29bdb9
            repo_from, "main", "fork"
Patrick Uiterwijk 3f97f6
        ) as tempclone:
Slavek Kabrda 29bdb9
            for branchname in tempclone.repo.branches.remote:
Slavek Kabrda 29bdb9
                if (
Slavek Kabrda 29bdb9
                    branchname.startswith("origin/")
Slavek Kabrda 29bdb9
                    and branchname != "origin/HEAD"
Slavek Kabrda 29bdb9
                ):
Slavek Kabrda 29bdb9
                    locbranch = branchname[len("origin/") :]
Slavek Kabrda 29bdb9
                    if locbranch in tempclone.repo.branches.local:
Slavek Kabrda 29bdb9
                        continue
Slavek Kabrda 29bdb9
                    branch = tempclone.repo.branches.remote.get(branchname)
Slavek Kabrda 29bdb9
                    tempclone.repo.branches.local.create(
Slavek Kabrda 29bdb9
                        locbranch, branch.peel()
Slavek Kabrda 29bdb9
                    )
Slavek Kabrda 29bdb9
            tempclone.change_project_association(repo_to)
Slavek Kabrda 29bdb9
            tempclone.mirror("pagure", internal_no_hooks="yes")
Patrick Uiterwijk 7b9080
Patrick Uiterwijk 3f97f6
        if not repo_to.is_on_repospanner and not repo_to.private:
Patrick Uiterwijk 3f97f6
            # Create the git-daemon-export-ok file on the clone
Patrick Uiterwijk 3f97f6
            http_clone_file = os.path.join(
Patrick Uiterwijk 3f97f6
                repo_to.repopath("main"), "git-daemon-export-ok"
Patrick Uiterwijk 7b9080
            )
Patrick Uiterwijk 3f97f6
            if not os.path.exists(http_clone_file):
Patrick Uiterwijk 3f97f6
                with open(http_clone_file, "w"):
Patrick Uiterwijk 3f97f6
                    pass
Patrick Uiterwijk 7b9080
Patrick Uiterwijk 7b9080
        pagure.lib.notify.log(
Patrick Uiterwijk 7b9080
            repo_to,
Pierre-Yves Chibon 9c2953
            topic="project.forked",
Pierre-Yves Chibon 9c2953
            msg=dict(project=repo_to.to_json(public=True), agent=user_forker),
Patrick Uiterwijk ac056b
        )
Patrick Uiterwijk ac056b
Pierre-Yves Chibon 9c2953
    _log.info("Project created, refreshing auth async")
Pierre-Yves Chibon 56e29f
    task = generate_gitolite_acls.delay(
Pierre-Yves Chibon 274e60
        namespace=repo_to.namespace,
Pierre-Yves Chibon 274e60
        name=repo_to.name,
Pierre-Yves Chibon 9c2953
        user=repo_to.user.user if repo_to.is_fork else None,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 9c2953
    _log.info("Refreshing gitolite config queued in task: %s", task.id)
Patrick Uiterwijk 2a3bd8
Patrick Uiterwijk 2a3bd8
    if editfile is None:
Pierre-Yves Chibon 9c2953
        return ret(
Pierre-Yves Chibon 9c2953
            "ui_ns.view_repo",
Pierre-Yves Chibon 9c2953
            repo=name,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
            username=user_forker,
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk 2a3bd8
    else:
Pierre-Yves Chibon 9c2953
        return ret(
Pierre-Yves Chibon 9c2953
            "ui_ns.edit_file",
Pierre-Yves Chibon 9c2953
            repo=name,
Pierre-Yves Chibon 9c2953
            namespace=namespace,
Pierre-Yves Chibon 9c2953
            username=user_forker,
Pierre-Yves Chibon 9c2953
            branchname=editbranch,
Pierre-Yves Chibon 9c2953
            filename=editfile,
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk c0c627
Patrick Uiterwijk c0c627
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda efeaa6
def pull_remote_repo(self, session, remote_git, branch_from):
Pierre-Yves Chibon 314da3
    """ Clone a remote git repository locally for remote PRs.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon f2db4b
Pierre-Yves Chibon b9d537
    clonepath = pagure.utils.get_remote_repo_path(
Pierre-Yves Chibon 9c2953
        remote_git, branch_from, ignore_non_exist=True
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon b9d537
Pierre-Yves Chibon a87742
    pagure.lib.repo.PagureRepo.clone(
Pierre-Yves Chibon 9c2953
        remote_git, clonepath, checkout_branch=branch_from
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk c0c627
Patrick Uiterwijk 226add
    return clonepath
Patrick Uiterwijk c6f63a
Patrick Uiterwijk c6f63a
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda efeaa6
def refresh_remote_pr(self, session, name, namespace, user, requestid):
Pierre-Yves Chibon 314da3
    """ Refresh the local clone of a git repository used in a remote
Pierre-Yves Chibon 314da3
    pull-request.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 04c084
Pierre-Yves Chibon 930073
    request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
        session, project_id=project.id, requestid=requestid
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 04c084
    _log.debug(
Pierre-Yves Chibon 9c2953
        "refreshing remote pull-request: %s/#%s",
Pierre-Yves Chibon 9c2953
        request.project.fullname,
Pierre-Yves Chibon 9c2953
        request.id,
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 04c084
Pierre-Yves Chibon b8cacb
    clonepath = pagure.utils.get_remote_repo_path(
Pierre-Yves Chibon 9c2953
        request.remote_git, request.branch_from
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 04c084
Patrick Uiterwijk 04c084
    repo = pagure.lib.repo.PagureRepo(clonepath)
Patrick Uiterwijk 04c084
    repo.pull(branch=request.branch_from, force=True)
Patrick Uiterwijk 04c084
Patrick Uiterwijk 04c084
    refresh_pr_cache.delay(name, namespace, user)
Patrick Uiterwijk 04c084
    del repo
Pierre-Yves Chibon b130e5
    return ret(
Pierre-Yves Chibon 9c2953
        "ui_ns.request_pull",
Pierre-Yves Chibon 9c2953
        username=user,
Pierre-Yves Chibon 9c2953
        namespace=namespace,
Pierre-Yves Chibon 9c2953
        repo=name,
Pierre-Yves Chibon 9c2953
        requestid=requestid,
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 04c084
Patrick Uiterwijk 04c084
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Patrick Uiterwijk 3f97f6
def move_to_repospanner(self, session, name, namespace, user, region):
Patrick Uiterwijk 3f97f6
    """ Move a repository to a repoSpanner region.
Patrick Uiterwijk 3f97f6
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Patrick Uiterwijk 3f97f6
        session, namespace=namespace, name=name, user=user
Patrick Uiterwijk 3f97f6
    )
Patrick Uiterwijk 3f97f6
    regioninfo = pagure_config.get("REPOSPANNER_REGIONS", {}).get(region)
Patrick Uiterwijk 3f97f6
    if not regioninfo:
Patrick Uiterwijk 3f97f6
        raise Exception("Missing region config")
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
    with project.lock("WORKER"):
Patrick Uiterwijk 3f97f6
        # Perform some pre-flight checks
Patrick Uiterwijk 3f97f6
        if project.is_on_repospanner:
Patrick Uiterwijk 3f97f6
            raise Exception("Project is already on repoSpanner")
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        #  Make sure that no non-runner hooks are enabled for this project
Patrick Uiterwijk 3f97f6
        incompatible_hooks = []
Slavek Kabrda 0915d0
        for repotype in pagure.lib.query.get_repotypes():
Patrick Uiterwijk 3f97f6
            path = project.repopath(repotype)
Patrick Uiterwijk c08d9c
            if path is None:
Patrick Uiterwijk c08d9c
                continue
Patrick Uiterwijk 3f97f6
            hookpath = os.path.join(path, "hooks")
Patrick Uiterwijk 3f97f6
            for hook in os.listdir(hookpath):
Patrick Uiterwijk 3f97f6
                if not hook.startswith(
Patrick Uiterwijk 3f97f6
                    ("pre-receive.", "update.", "post-receive.")
Patrick Uiterwijk 3f97f6
                ):
Patrick Uiterwijk 3f97f6
                    continue
Patrick Uiterwijk 05520e
                if hook.endswith(".sample"):
Patrick Uiterwijk 05520e
                    # Ignore the samples that Git inserts
Patrick Uiterwijk 05520e
                    continue
Pierre-Yves Chibon 4937c4
                if hook not in pagure.lib.query.ORIGINAL_PAGURE_HOOK:
Patrick Uiterwijk 3f97f6
                    incompatible_hooks.append((repotype, hook))
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        if incompatible_hooks:
Patrick Uiterwijk 3f97f6
            raise Exception(
Patrick Uiterwijk 3f97f6
                "Repository contains repoSpanner-incompatible "
Patrick Uiterwijk 87315e
                "hooks: %s"
Patrick Uiterwijk 87315e
                % ", ".join(["%s" % (hook,) for hook in incompatible_hooks])
Patrick Uiterwijk 3f97f6
            )
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        # Create the repositories
Patrick Uiterwijk 3f97f6
        pagure.lib.git.create_project_repos(project, region, None, False)
Patrick Uiterwijk 3f97f6
Slavek Kabrda 0915d0
        for repotype in pagure.lib.query.get_repotypes():
Patrick Uiterwijk 3f97f6
            repopath = project.repopath(repotype)
Patrick Uiterwijk aeb045
            if repopath is None:
Patrick Uiterwijk aeb045
                continue
Patrick Uiterwijk aeb045
            repourl, _ = project.repospanner_repo_info(repotype, region)
Patrick Uiterwijk 3f97f6
            repo_obj = pagure.lib.repo.PagureRepo(repopath)
Patrick Uiterwijk 3f97f6
            repo_obj.create_remote("repospanner_push", repourl)
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
            command = [
Patrick Uiterwijk 3f97f6
                "git",
Patrick Uiterwijk 3f97f6
                "-c",
Patrick Uiterwijk 3f97f6
                "http.sslcainfo=%s" % regioninfo["ca"],
Patrick Uiterwijk 3f97f6
                "-c",
Patrick Uiterwijk 3f97f6
                "http.sslcert=%s" % regioninfo["push_cert"]["cert"],
Patrick Uiterwijk 3f97f6
                "-c",
Patrick Uiterwijk 3f97f6
                "http.sslkey=%s" % regioninfo["push_cert"]["key"],
Patrick Uiterwijk 3f97f6
                "push",
Patrick Uiterwijk 3f97f6
                "--mirror",
Patrick Uiterwijk 3f97f6
                "repospanner_push",
Patrick Uiterwijk 3f97f6
            ]
Patrick Uiterwijk 3f97f6
            _log.debug("Running push command: %s", command)
Patrick Uiterwijk 3f97f6
            out = subprocess.check_output(
Patrick Uiterwijk 3f97f6
                command, cwd=repopath, stderr=subprocess.STDOUT
Patrick Uiterwijk 3f97f6
            )
Patrick Uiterwijk 3f97f6
            _log.debug("Out: %s" % out)
Patrick Uiterwijk 3f97f6
Slavek Kabrda 0915d0
        for repotype in pagure.lib.query.get_repotypes():
Patrick Uiterwijk 3f97f6
            repopath = project.repopath(repotype)
Patrick Uiterwijk bad007
            if repopath is None:
Patrick Uiterwijk bad007
                continue
Patrick Uiterwijk 3f97f6
            repo_obj = pagure.lib.repo.PagureRepo(repopath)
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
            # At this moment, this subrepo has been migrated
Patrick Uiterwijk 3f97f6
            # Move the "refs" folder to "refsold", so that we don't actually
Patrick Uiterwijk 3f97f6
            # delete any data, but it's no longer a valid git repo.
Patrick Uiterwijk 3f97f6
            # On next use, a pseudo repository will be created.
Patrick Uiterwijk 3f97f6
            refsdir = os.path.join(repopath, "refs")
Patrick Uiterwijk 3f97f6
            shutil.move(refsdir, refsdir + "old")
Patrick Uiterwijk 3f97f6
            with open(
Patrick Uiterwijk 3f97f6
                os.path.join(repopath, "repospanner_status"), "w"
Patrick Uiterwijk 3f97f6
            ) as info:
Patrick Uiterwijk 3f97f6
                info.write(
Patrick Uiterwijk 3f97f6
                    "This repository has migrated to repoSpanner region %s"
Patrick Uiterwijk 3f97f6
                    % region
Patrick Uiterwijk 3f97f6
                )
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        project.repospanner_region = region
Patrick Uiterwijk 3f97f6
        session.add(project)
Patrick Uiterwijk 3f97f6
        session.commit()
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
    return ret(
Patrick Uiterwijk 3f97f6
        "ui_ns.view_repo", username=user, namespace=namespace, repo=name
Patrick Uiterwijk 3f97f6
    )
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Patrick Uiterwijk 3f97f6
@pagure_task
Pierre-Yves Chibon ca7bbc
def refresh_pr_cache(self, session, name, namespace, user, but_uids=None):
Pierre-Yves Chibon 314da3
    """ Refresh the merge status cached of pull-requests.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk c6f63a
Pierre-Yves Chibon ca7bbc
    pagure.lib.query.reset_status_pull_request(
Pierre-Yves Chibon ca7bbc
        session, project, but_uids=but_uids
Pierre-Yves Chibon ca7bbc
    )
Patrick Uiterwijk c6f63a
Patrick Uiterwijk 3caaa0
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Pierre-Yves Chibon b9aec2
def rebase_pull_request(
Pierre-Yves Chibon b9aec2
    self, session, name, namespace, user, requestid, user_rebaser
Pierre-Yves Chibon b9aec2
):
Pierre-Yves Chibon b9aec2
    """ Rebase a pull-request.
Pierre-Yves Chibon b9aec2
    """
Pierre-Yves Chibon b9aec2
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon b9aec2
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon b9aec2
    )
Pierre-Yves Chibon d91c53
    _log.info("Rebase PR: %s of project: %s" % (requestid, project.fullname))
Pierre-Yves Chibon b9aec2
Pierre-Yves Chibon b9aec2
    with project.lock("WORKER"):
Pierre-Yves Chibon b9aec2
        request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon b9aec2
            session, project_id=project.id, requestid=requestid
Pierre-Yves Chibon b9aec2
        )
Pierre-Yves Chibon b9aec2
        _log.debug(
Pierre-Yves Chibon d91c53
            "Rebasing pull-request: %s#%s, uid: %s",
Pierre-Yves Chibon b9aec2
            request.project.fullname,
Pierre-Yves Chibon b9aec2
            request.id,
Pierre-Yves Chibon d91c53
            request.uid,
Pierre-Yves Chibon b9aec2
        )
Pierre-Yves Chibon 011b16
        pagure.lib.git.rebase_pull_request(session, request, user_rebaser)
Pierre-Yves Chibon b9aec2
Pierre-Yves Chibon b983f9
    update_pull_request(request.uid, username=user_rebaser)
Pierre-Yves Chibon b9aec2
    # Schedule refresh of all opened PRs
Pierre-Yves Chibon b9aec2
    pagure.lib.query.reset_status_pull_request(session, request.project)
Pierre-Yves Chibon b9aec2
Pierre-Yves Chibon b9aec2
Pierre-Yves Chibon b9aec2
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Pierre-Yves Chibon b9aec2
@pagure_task
Pierre-Yves Chibon 9c2953
def merge_pull_request(
Pierre-Yves Chibon 9c2953
    self,
Pierre-Yves Chibon 9c2953
    session,
Pierre-Yves Chibon 9c2953
    name,
Pierre-Yves Chibon 9c2953
    namespace,
Pierre-Yves Chibon 9c2953
    user,
Pierre-Yves Chibon 9c2953
    requestid,
Pierre-Yves Chibon 9c2953
    user_merger,
Pierre-Yves Chibon 9c2953
    delete_branch_after=False,
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 314da3
    """ Merge pull-request.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 9c2953
    with project.lock("WORKER"):
Pierre-Yves Chibon 930073
        request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
            session, project_id=project.id, requestid=requestid
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 8be363
        _log.debug(
Pierre-Yves Chibon 9c2953
            "Merging pull-request: %s/#%s",
Pierre-Yves Chibon 9c2953
            request.project.fullname,
Pierre-Yves Chibon 9c2953
            request.id,
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk 3f97f6
        pagure.lib.git.merge_pull_request(session, request, user_merger)
Patrick Uiterwijk c6f63a
LubomĂ­r SedlĂ¡Å™ 7c6b11
    if delete_branch_after:
Pierre-Yves Chibon 9c2953
        _log.debug(
Pierre-Yves Chibon 9c2953
            "Will delete source branch of pull-request: %s/#%s",
Pierre-Yves Chibon 9c2953
            request.project.fullname,
Pierre-Yves Chibon 9c2953
            request.id,
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 9c2953
        owner = (
Pierre-Yves Chibon 9c2953
            request.project_from.user.username
Pierre-Yves Chibon 9c2953
            if request.project_from.parent
Pierre-Yves Chibon 9c2953
            else None
Pierre-Yves Chibon 9c2953
        )
LubomĂ­r SedlĂ¡Å™ 7c6b11
        delete_branch.delay(
LubomĂ­r SedlĂ¡Å™ 7c6b11
            request.project_from.name,
LubomĂ­r SedlĂ¡Å™ 7c6b11
            request.project_from.namespace,
LubomĂ­r SedlĂ¡Å™ ed7075
            owner,
Pierre-Yves Chibon 9c2953
            request.branch_from,
Pierre-Yves Chibon 9c2953
        )
LubomĂ­r SedlĂ¡Å™ 7c6b11
Patrick Uiterwijk c6f63a
    refresh_pr_cache.delay(name, namespace, user)
Pierre-Yves Chibon b130e5
    return ret(
Julen Landa Alustiza 6725ec
        "ui_ns.request_pull",
Julen Landa Alustiza 6725ec
        repo=name,
Julen Landa Alustiza 6725ec
        requestid=requestid,
Julen Landa Alustiza 6725ec
        username=user,
Julen Landa Alustiza 6725ec
        namespace=namespace,
Pierre-Yves Chibon 9c2953
    )
Patrick Uiterwijk 96c928
Patrick Uiterwijk 96c928
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Pierre-Yves Chibon 9c2953
def add_file_to_git(
Pierre-Yves Chibon 9c2953
    self, session, name, namespace, user, user_attacher, issueuid, filename
Pierre-Yves Chibon 9c2953
):
Pierre-Yves Chibon 314da3
    """ Add a file to the specified git repo.
Pierre-Yves Chibon 314da3
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 9c2953
    with project.lock("WORKER"):
Pierre-Yves Chibon 930073
        issue = pagure.lib.query.get_issue_by_uid(session, issueuid)
Pierre-Yves Chibon 930073
        user_attacher = pagure.lib.query.search_user(
Pierre-Yves Chibon 930073
            session, username=user_attacher
Pierre-Yves Chibon 930073
        )
Patrick Uiterwijk 96c928
Pierre-Yves Chibon 9c2953
        from_folder = pagure_config["ATTACHMENTS_FOLDER"]
Pierre-Yves Chibon 8be363
        _log.info(
Patrick Uiterwijk 3f97f6
            "Adding file %s from %s to %s",
Patrick Uiterwijk 3f97f6
            filename,
Patrick Uiterwijk 3f97f6
            from_folder,
Patrick Uiterwijk 3f97f6
            project.fullname,
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk 7b9080
        pagure.lib.git._add_file_to_git(
Patrick Uiterwijk 3f97f6
            project, issue, from_folder, user_attacher, filename
Pierre-Yves Chibon 9c2953
        )
Patrick Uiterwijk 96c928
Patrick Uiterwijk 7b9080
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda efeaa6
def project_dowait(self, session, name, namespace, user):
Patrick Uiterwijk 7b9080
    """ This is a task used to test the locking systems.
Patrick Uiterwijk 7b9080
Patrick Uiterwijk 7b9080
    It should never be allowed to be called in production instances, since that
Patrick Uiterwijk 7b9080
    would allow an attacker to basically DOS a project by calling this
Patrick Uiterwijk 7b9080
    repeatedly. """
Pierre-Yves Chibon 9c2953
    assert pagure_config.get("ALLOW_PROJECT_DOWAIT", False)
Pierre-Yves Chibon f2db4b
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon edbdc9
Pierre-Yves Chibon 9c2953
    with project.lock("WORKER"):
Patrick Uiterwijk 7b9080
        time.sleep(10)
Patrick Uiterwijk 7b9080
Pierre-Yves Chibon b130e5
    return ret(
Pierre-Yves Chibon 9c2953
        "ui_ns.view_repo", repo=name, username=user, namespace=namespace
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon acd3eb
Pierre-Yves Chibon acd3eb
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda efeaa6
def sync_pull_ref(self, session, name, namespace, user, requestid):
Pierre-Yves Chibon acd3eb
    """ Synchronize a pull/ reference from the content in the forked repo,
Pierre-Yves Chibon acd3eb
    allowing local checkout of the pull-request.
Pierre-Yves Chibon acd3eb
    """
Pierre-Yves Chibon 930073
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon 9c2953
        session, namespace=namespace, name=name, user=user
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon acd3eb
Pierre-Yves Chibon 9c2953
    with project.lock("WORKER"):
Pierre-Yves Chibon 930073
        request = pagure.lib.query.search_pull_requests(
Pierre-Yves Chibon 9c2953
            session, project_id=project.id, requestid=requestid
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon acd3eb
        _log.debug(
Pierre-Yves Chibon 9c2953
            "Update pull refs of: %s#%s", request.project.fullname, request.id
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon acd3eb
Pierre-Yves Chibon acd3eb
        if request.remote:
Pierre-Yves Chibon acd3eb
            # Get the fork
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 c96124
        elif request.project_from:
Pierre-Yves Chibon acd3eb
            # Get the fork
Pierre-Yves Chibon b130e5
            repopath = pagure.utils.get_repo_path(request.project_from)
Pierre-Yves Chibon c96124
        else:
Pierre-Yves Chibon c96124
            return
Pierre-Yves Chibon 9c2953
        _log.debug("   working on the repo in: %s", repopath)
Pierre-Yves Chibon acd3eb
Pierre-Yves Chibon acd3eb
        repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon acd3eb
        pagure.lib.git.update_pull_ref(request, repo_obj)
Pierre-Yves Chibon acd3eb
Pierre-Yves Chibon 36309a
Pierre-Yves Chibon 974201
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Pierre-Yves Chibon 974201
@pagure_task
Pierre-Yves Chibon b983f9
def update_pull_request(self, session, pr_uid, username=None):
Pierre-Yves Chibon 974201
    """ Updates a pull-request in the DB once a commit was pushed to it in
Pierre-Yves Chibon 974201
    git.
Pierre-Yves Chibon 974201
    """
Pierre-Yves Chibon 930073
    request = pagure.lib.query.get_request_by_uid(session, pr_uid)
Pierre-Yves Chibon 974201
Pierre-Yves Chibon 974201
    with request.project.lock("WORKER"):
Pierre-Yves Chibon 974201
Pierre-Yves Chibon 974201
        _log.debug(
Pierre-Yves Chibon 974201
            "Updating pull-request: %s#%s",
Pierre-Yves Chibon 974201
            request.project.fullname,
Pierre-Yves Chibon 974201
            request.id,
Pierre-Yves Chibon 974201
        )
Pierre-Yves Chibon 974201
Pierre-Yves Chibon a093e7
        try:
Pierre-Yves Chibon a093e7
            pagure.lib.git.merge_pull_request(
Pierre-Yves Chibon b983f9
                session=session,
Pierre-Yves Chibon b983f9
                request=request,
Pierre-Yves Chibon b983f9
                username=username,
Pierre-Yves Chibon b983f9
                domerge=False,
Pierre-Yves Chibon a093e7
            )
Pierre-Yves Chibon a093e7
        except pagure.exceptions.PagureException as err:
Pierre-Yves Chibon a093e7
            _log.debug(err)
Pierre-Yves Chibon 974201
Pierre-Yves Chibon 974201
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda efeaa6
def update_checksums_file(self, session, folder, filenames):
Pierre-Yves Chibon 314da3
    """ Update the checksums file in the release folder of the project.
Pierre-Yves Chibon 36309a
    """
Pierre-Yves Chibon f2db4b
Pierre-Yves Chibon 9c2953
    sha_file = os.path.join(folder, "CHECKSUMS")
Pierre-Yves Chibon 36309a
    new_file = not os.path.exists(sha_file)
Pierre-Yves Chibon 36309a
Pierre-Yves Chibon 36309a
    if not new_file:
Pierre-Yves Chibon 36309a
        with open(sha_file) as stream:
Pierre-Yves Chibon 36309a
            row = stream.readline().strip()
Pierre-Yves Chibon 9c2953
            if row != "# Generated and updated by pagure":
Pierre-Yves Chibon 36309a
                # This wasn't generated by pagure, don't touch it!
Pierre-Yves Chibon 36309a
                return
Pierre-Yves Chibon 36309a
Pierre-Yves Chibon 36309a
    for filename in filenames:
Pierre-Yves Chibon 9c2953
        algos = {"sha256": hashlib.sha256(), "sha512": hashlib.sha512()}
Pierre-Yves Chibon 36309a
        # for each files computes the different algorythm supported
Pierre-Yves Chibon 36309a
        with open(os.path.join(folder, filename), "rb") as stream:
Pierre-Yves Chibon 36309a
            while True:
Pierre-Yves Chibon 36309a
                buf = stream.read(2 * 2 ** 10)
Pierre-Yves Chibon 36309a
                if buf:
Pierre-Yves Chibon 36309a
                    for hasher in algos.values():
Pierre-Yves Chibon 36309a
                        hasher.update(buf)
Pierre-Yves Chibon 36309a
                else:
Pierre-Yves Chibon 36309a
                    break
Pierre-Yves Chibon 36309a
Pierre-Yves Chibon 36309a
        # Write them out to the output file
Pierre-Yves Chibon 9c2953
        with open(sha_file, "a") as stream:
Pierre-Yves Chibon 36309a
            if new_file:
Pierre-Yves Chibon 9c2953
                stream.write("# Generated and updated by pagure\n")
Pierre-Yves Chibon 4c06f0
                new_file = False
Aurélien Bompard f61bb3
            for algo in sorted(algos):
Pierre-Yves Chibon 9c2953
                stream.write(
Pierre-Yves Chibon 9c2953
                    "%s (%s) = %s\n"
Pierre-Yves Chibon 9c2953
                    % (algo.upper(), filename, algos[algo].hexdigest())
Pierre-Yves Chibon 9c2953
                )
Pierre-Yves Chibon 716362
Pierre-Yves Chibon 716362
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda efeaa6
def commits_author_stats(self, session, repopath):
Pierre-Yves Chibon 716362
    """ Returns some statistics about commits made against the specified
Pierre-Yves Chibon 716362
    git repository.
Pierre-Yves Chibon 716362
    """
Pierre-Yves Chibon f2db4b
Pierre-Yves Chibon 716362
    if not os.path.exists(repopath):
Pierre-Yves Chibon 9c2953
        raise ValueError("Git repository not found.")
Pierre-Yves Chibon 716362
Pierre-Yves Chibon 716362
    repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon 716362
Pierre-Yves Chibon 716362
    stats = collections.defaultdict(int)
LubomĂ­r SedlĂ¡Å™ 444e6e
    number_of_commits = 0
Pierre-Yves Chibon 716362
    authors_email = set()
Pierre-Yves Chibon 716362
    for commit in repo_obj.walk(
Pierre-Yves Chibon 29ff0a
        repo_obj.head.peel().oid.hex, pygit2.GIT_SORT_NONE
Pierre-Yves Chibon 9c2953
    ):
LubomĂ­r SedlĂ¡Å™ 444e6e
        # For each commit record how many times each combination of name and
LubomĂ­r SedlĂ¡Å™ 444e6e
        # e-mail appears in the git history.
LubomĂ­r SedlĂ¡Å™ 444e6e
        number_of_commits += 1
Pierre-Yves Chibon 716362
        email = commit.author.email
Pierre-Yves Chibon 716362
        author = commit.author.name
Pierre-Yves Chibon 716362
        stats[(author, email)] += 1
Pierre-Yves Chibon 716362
Pierre-Yves Chibon f2fe29
    for (name, email), val in list(stats.items()):
LubomĂ­r SedlĂ¡Å™ 4c386f
        if not email:
LubomĂ­r SedlĂ¡Å™ 4c386f
            # Author email is missing in the git commit.
LubomĂ­r SedlĂ¡Å™ 4c386f
            continue
LubomĂ­r SedlĂ¡Å™ 444e6e
        # For each recorded user info, check if we know the e-mail address of
LubomĂ­r SedlĂ¡Å™ 444e6e
        # the user.
Pierre-Yves Chibon 930073
        user = pagure.lib.query.search_user(session, email=email)
LubomĂ­r SedlĂ¡Å™ 444e6e
        if user and (user.default_email != email or user.fullname != name):
LubomĂ­r SedlĂ¡Å™ 444e6e
            # We know the the user, but the name or e-mail used in Git commit
LubomĂ­r SedlĂ¡Å™ 444e6e
            # does not match their default e-mail address and full name. Let's
LubomĂ­r SedlĂ¡Å™ 444e6e
            # merge them into one record.
LubomĂ­r SedlĂ¡Å™ 444e6e
            stats.pop((name, email))
LubomĂ­r SedlĂ¡Å™ 444e6e
            stats[(user.fullname, user.default_email)] += val
LubomĂ­r SedlĂ¡Å™ 444e6e
LubomĂ­r SedlĂ¡Å™ 444e6e
    # Generate a list of contributors ordered by how many commits they
LubomĂ­r SedlĂ¡Å™ 444e6e
    # authored. The list consists of tuples with number of commits and people
Pierre-Yves Chibon 409376
    # with that number of commits. Each contributor is represented by a tuple
Pierre-Yves Chibon 409376
    # of name, e-mail address and avatar url.
Pierre-Yves Chibon 716362
    out_stats = collections.defaultdict(list)
Pierre-Yves Chibon 716362
    for authors, val in stats.items():
LubomĂ­r SedlĂ¡Å™ 444e6e
        authors_email.add(authors[1])
Pierre-Yves Chibon 409376
        out_authors = list(authors)
Pierre-Yves Chibon 409376
        out_authors.append(
Pierre-Yves Chibon 409376
            pagure.lib.query.avatar_url_from_email(authors[1], size=32)
Pierre-Yves Chibon 409376
        )
Pierre-Yves Chibon 409376
        out_stats[val].append(tuple(out_authors))
Pierre-Yves Chibon 609c2b
    out_list = [
Pierre-Yves Chibon 9c2953
        (key, out_stats[key]) for key in sorted(out_stats, reverse=True)
Pierre-Yves Chibon 609c2b
    ]
Pierre-Yves Chibon 716362
LubomĂ­r SedlĂ¡Å™ 444e6e
    return (
LubomĂ­r SedlĂ¡Å™ 444e6e
        number_of_commits,
LubomĂ­r SedlĂ¡Å™ 444e6e
        out_list,
LubomĂ­r SedlĂ¡Å™ 444e6e
        len(authors_email),
Pierre-Yves Chibon 9c2953
        commit.commit_time,
LubomĂ­r SedlĂ¡Å™ 444e6e
    )
Pierre-Yves Chibon 1828a2
Pierre-Yves Chibon 1828a2
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Slavek Kabrda efeaa6
@pagure_task
Slavek Kabrda efeaa6
def commits_history_stats(self, session, repopath):
Pierre-Yves Chibon 1828a2
    """ Returns the evolution of the commits made against the specified
Pierre-Yves Chibon 1828a2
    git repository.
Pierre-Yves Chibon 1828a2
    """
Pierre-Yves Chibon f2db4b
Pierre-Yves Chibon 1828a2
    if not os.path.exists(repopath):
Pierre-Yves Chibon 9c2953
        raise ValueError("Git repository not found.")
Pierre-Yves Chibon 1828a2
Pierre-Yves Chibon 1828a2
    repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon 1828a2
Pierre-Yves Chibon 1828a2
    dates = collections.defaultdict(int)
Pierre-Yves Chibon 1828a2
    for commit in repo_obj.walk(
Pierre-Yves Chibon 29ff0a
        repo_obj.head.peel().oid.hex, pygit2.GIT_SORT_NONE
Pierre-Yves Chibon 9c2953
    ):
Pierre-Yves Chibon 9c2953
        delta = (
Pierre-Yves Chibon 9c2953
            datetime.datetime.utcnow() - arrow.get(commit.commit_time).naive
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 1828a2
        if delta.days > 365:
Pierre-Yves Chibon 1828a2
            break
Pierre-Yves Chibon 1828a2
        dates[arrow.get(commit.commit_time).date().isoformat()] += 1
Pierre-Yves Chibon 1828a2
Pierre-Yves Chibon 1828a2
    return [(key, dates[key]) for key in sorted(dates)]
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 9c2953
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Pierre-Yves Chibon 11d019
@pagure_task
Pierre-Yves Chibon 11d019
def link_pr_to_ticket(self, session, pr_uid):
Pierre-Yves Chibon 11d019
    """ Link the specified pull-request against the ticket(s) mentioned in
Pierre-Yves Chibon 11d019
    the commits of the pull-request
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
    """
Pierre-Yves Chibon 9c2953
    _log.info("LINK_PR_TO_TICKET: Linking ticket(s) to PR for: %s" % pr_uid)
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 930073
    request = pagure.lib.query.get_request_by_uid(session, pr_uid)
Pierre-Yves Chibon 11d019
    if not request:
Pierre-Yves Chibon 9c2953
        _log.info("LINK_PR_TO_TICKET: Not PR found for: %s" % pr_uid)
Pierre-Yves Chibon 11d019
        return
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
    if request.remote:
Pierre-Yves Chibon 11d019
        repopath = pagure.utils.get_remote_repo_path(
Pierre-Yves Chibon 9c2953
            request.remote_git, request.branch_from
Pierre-Yves Chibon 9c2953
        )
Pierre-Yves Chibon 11d019
        parentpath = pagure.utils.get_repo_path(request.project)
Pierre-Yves Chibon 017f49
    elif request.project_from:
Pierre-Yves Chibon 11d019
        repo_from = request.project_from
Pierre-Yves Chibon 11d019
        repopath = pagure.utils.get_repo_path(repo_from)
Pierre-Yves Chibon 11d019
        parentpath = get_parent_repo_path(repo_from)
Pierre-Yves Chibon 017f49
    else:
Pierre-Yves Chibon 017f49
        _log.info(
Pierre-Yves Chibon 017f49
            "LINK_PR_TO_TICKET: PR neither remote, nor with a "
Pierre-Yves Chibon accad9
            "project_from, bailing: %s" % pr_uid
Pierre-Yves Chibon accad9
        )
Pierre-Yves Chibon 017f49
        return
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 2479ca
    # Drop the existing commit-based relations
Pierre-Yves Chibon 2479ca
    session.query(pagure.lib.model.PrToIssue).filter(
Pierre-Yves Chibon 2479ca
        pagure.lib.model.PrToIssue.pull_request_uid == request.uid
Pierre-Yves Chibon 2479ca
    ).filter(pagure.lib.model.PrToIssue.origin == "intial_comment_pr").delete(
Pierre-Yves Chibon 2479ca
        synchronize_session="fetch"
Pierre-Yves Chibon 2479ca
    )
Pierre-Yves Chibon 2479ca
Pierre-Yves Chibon 11d019
    repo_obj = pygit2.Repository(repopath)
Pierre-Yves Chibon 11d019
    orig_repo = pygit2.Repository(parentpath)
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
    diff_commits = pagure.lib.git.diff_pull_request(
Pierre-Yves Chibon 35fe76
        session, request, repo_obj, orig_repo, with_diff=False, notify=False
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
    _log.info(
Pierre-Yves Chibon 9c2953
        "LINK_PR_TO_TICKET: Found %s commits in that PR" % len(diff_commits)
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
    name = request.project.name
Pierre-Yves Chibon 11d019
    namespace = request.project.namespace
Pierre-Yves Chibon 9c2953
    user = request.project.user.user if request.project.is_fork else None
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
    for line in pagure.lib.git.read_git_lines(
Pierre-Yves Chibon 9c2953
        ["log", "--no-walk"] + [c.oid.hex for c in diff_commits] + ["--"],
Pierre-Yves Chibon 9c2953
        repopath,
Pierre-Yves Chibon 9c2953
    ):
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
        line = line.strip()
Pierre-Yves Chibon 11d019
        for issue in pagure.lib.link.get_relation(
Pierre-Yves Chibon 9c2953
            session, name, user, namespace, line, "fixes", include_prs=False
Pierre-Yves Chibon 9c2953
        ):
Pierre-Yves Chibon 11d019
            _log.info(
Pierre-Yves Chibon 9c2953
                "LINK_PR_TO_TICKET: Link ticket %s to PRs %s"
Pierre-Yves Chibon 9c2953
                % (issue, request)
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 2479ca
            pagure.lib.query.link_pr_issue(
Pierre-Yves Chibon 2479ca
                session, issue, request, origin="commit"
Pierre-Yves Chibon 2479ca
            )
Pierre-Yves Chibon 11d019
Pierre-Yves Chibon 11d019
        for issue in pagure.lib.link.get_relation(
Pierre-Yves Chibon 9c2953
            session, name, user, namespace, line, "relates"
Pierre-Yves Chibon 9c2953
        ):
Pierre-Yves Chibon 11d019
            _log.info(
Pierre-Yves Chibon 9c2953
                "LINK_PR_TO_TICKET: Link ticket %s to PRs %s"
Pierre-Yves Chibon 9c2953
                % (issue, request)
Pierre-Yves Chibon 9c2953
            )
Pierre-Yves Chibon 2479ca
            pagure.lib.query.link_pr_issue(
Pierre-Yves Chibon 2479ca
                session, issue, request, origin="commit"
Pierre-Yves Chibon 2479ca
            )
Pierre-Yves Chibon 8584f3
Pierre-Yves Chibon 8584f3
    try:
Pierre-Yves Chibon 8584f3
        session.commit()
Pierre-Yves Chibon 8584f3
    except SQLAlchemyError:
Pierre-Yves Chibon 9c2953
        _log.exception("Could not link ticket to PR :(")
Pierre-Yves Chibon 8584f3
        session.rollback()
Karsten Hopp 0a3020
Karsten Hopp 0a3020
Karsten Hopp 0a3020
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Karsten Hopp 0a3020
@pagure_task
Karsten Hopp 0a3020
def pull_request_ready_branch(self, session, namespace, name, user):
Pierre-Yves Chibon 930073
    repo = pagure.lib.query._get_project(
Karsten Hopp 0a3020
        session, name, user=user, namespace=namespace
Karsten Hopp 0a3020
    )
Karsten Hopp 0a3020
    repo_obj = pygit2.Repository(pagure.utils.get_repo_path(repo))
Karsten Hopp 0a3020
Karsten Hopp 0a3020
    if repo.is_fork and repo.parent:
Karsten Hopp 0a3020
        parentreponame = pagure.utils.get_repo_path(repo.parent)
Karsten Hopp 0a3020
        parent_repo_obj = pygit2.Repository(parentreponame)
Karsten Hopp 0a3020
    else:
Karsten Hopp 0a3020
        parent_repo_obj = repo_obj
Karsten Hopp 0a3020
Karsten Hopp 0a3020
    branches = {}
Karsten Hopp 0a3020
    if not repo_obj.is_empty and len(repo_obj.listall_branches()) > 0:
Karsten Hopp 0a3020
        for branchname in repo_obj.listall_branches():
Karsten Hopp 0a3020
            compare_branch = None
Karsten Hopp 0a3020
            if (
Karsten Hopp 0a3020
                not parent_repo_obj.is_empty
Karsten Hopp 0a3020
                and not parent_repo_obj.head_is_unborn
Karsten Hopp 0a3020
            ):
Karsten Hopp 0a3020
                try:
Karsten Hopp 0a3020
                    if pagure.config.config.get(
Karsten Hopp 0a3020
                        "PR_TARGET_MATCHING_BRANCH", False
Karsten Hopp 0a3020
                    ):
Karsten Hopp 0a3020
                        # find parent branch which is the longest substring of
Karsten Hopp 0a3020
                        # branch that we're processing
Karsten Hopp 0a3020
                        compare_branch = ""
Karsten Hopp 0a3020
                        for parent_branch in parent_repo_obj.branches:
Karsten Hopp 0a3020
                            if (
Karsten Hopp 0a3020
                                not repo.is_fork
Karsten Hopp 0a3020
                                and branchname == parent_branch
Karsten Hopp 0a3020
                            ):
Karsten Hopp 0a3020
                                continue
Karsten Hopp 0a3020
                            if branchname.startswith(parent_branch) and len(
Karsten Hopp 0a3020
                                parent_branch
Karsten Hopp 0a3020
                            ) > len(compare_branch):
Karsten Hopp 0a3020
                                compare_branch = parent_branch
Karsten Hopp 0a3020
                        compare_branch = (
Karsten Hopp 0a3020
                            compare_branch or repo_obj.head.shorthand
Karsten Hopp 0a3020
                        )
Karsten Hopp 0a3020
                    else:
Karsten Hopp 0a3020
                        compare_branch = repo_obj.head.shorthand
Karsten Hopp 0a3020
                except pygit2.GitError:
Karsten Hopp 0a3020
                    pass  # let compare_branch be None
Karsten Hopp 0a3020
Karsten Hopp 0a3020
            # Do not compare a branch to itself
Karsten Hopp 0a3020
            if (
Karsten Hopp 0a3020
                not repo.is_fork
Karsten Hopp 0a3020
                and compare_branch
Karsten Hopp 0a3020
                and compare_branch == branchname
Karsten Hopp 0a3020
            ):
Karsten Hopp 0a3020
                continue
Karsten Hopp 0a3020
Karsten Hopp 0a3020
            diff_commits = None
Karsten Hopp 0a3020
            try:
Karsten Hopp 0a3020
                _, diff_commits, _ = pagure.lib.git.get_diff_info(
Karsten Hopp 0a3020
                    repo_obj, parent_repo_obj, branchname, compare_branch
Karsten Hopp 0a3020
                )
Karsten Hopp 0a3020
            except pagure.exceptions.PagureException:
Karsten Hopp 0a3020
                pass
Karsten Hopp 0a3020
Karsten Hopp 0a3020
            if diff_commits:
Karsten Hopp 0a3020
                branches[branchname] = {
Karsten Hopp 0a3020
                    "commits": len(list(diff_commits)),
Karsten Hopp 0a3020
                    "target_branch": compare_branch or "master",
Karsten Hopp 0a3020
                }
Karsten Hopp 0a3020
Pierre-Yves Chibon 930073
    prs = pagure.lib.query.search_pull_requests(
Karsten Hopp 0a3020
        session, project_id_from=repo.id, status="Open"
Karsten Hopp 0a3020
    )
Karsten Hopp 0a3020
    branches_pr = {}
Karsten Hopp 0a3020
    for pr in prs:
Karsten Hopp 0a3020
        if pr.branch_from in branches:
Karsten Hopp 0a3020
            branches_pr[pr.branch_from] = "%s/pull-request/%s" % (
Karsten Hopp 0a3020
                pr.project.url_path,
Karsten Hopp 0a3020
                pr.id,
Karsten Hopp 0a3020
            )
Pierre-Yves Chibon 6d4fc2
            del branches[pr.branch_from]
Karsten Hopp 0a3020
    return {"new_branch": branches, "branch_w_pr": branches_pr}
Slavek Kabrda de8507
Slavek Kabrda de8507
Slavek Kabrda de8507
@conn.task(queue=pagure_config.get("MEDIUM_CELERY_QUEUE", None), bind=True)
Slavek Kabrda de8507
@pagure_task
Slavek Kabrda de8507
def git_garbage_collect(self, session, repopath):
Slavek Kabrda de8507
    # libgit2 doesn't support "git gc" and probably never will:
Slavek Kabrda de8507
    # https://github.com/libgit2/libgit2/issues/3247
Slavek Kabrda de8507
    _log.info("Running 'git gc --auto' for repo %s", repopath)
Pierre-Yves Chibon 97d19d
    subprocess.check_output(["git", "gc", "--auto", "-q"], cwd=repopath)
Pierre-Yves Chibon ded1fa
Pierre-Yves Chibon ded1fa
Pierre-Yves Chibon ded1fa
@conn.task(queue=pagure_config.get("FAST_CELERY_QUEUE", None), bind=True)
Pierre-Yves Chibon ded1fa
@pagure_task
Pierre-Yves Chibon ded1fa
def generate_archive(
Pierre-Yves Chibon ded1fa
    self, session, project, namespace, username, commit, tag, name, archive_fmt
Pierre-Yves Chibon ded1fa
):
Pierre-Yves Chibon ded1fa
    """ Generate the archive of the specified project on the specified
Pierre-Yves Chibon ded1fa
    commit with the given name and archive format.
Pierre-Yves Chibon ded1fa
    Currently only support the following format: gzip and tar.gz
Pierre-Yves Chibon ded1fa
Pierre-Yves Chibon ded1fa
    """
Pierre-Yves Chibon ded1fa
    project = pagure.lib.query._get_project(
Pierre-Yves Chibon ded1fa
        session, namespace=namespace, name=project, user=username
Pierre-Yves Chibon ded1fa
    )
Pierre-Yves Chibon ded1fa
Pierre-Yves Chibon ded1fa
    _log.debug(
Pierre-Yves Chibon ded1fa
        "Generating archive for %s, commit: %s as: %s.%s",
Pierre-Yves Chibon ded1fa
        project.fullname,
Pierre-Yves Chibon ded1fa
        commit,
Pierre-Yves Chibon ded1fa
        name,
Pierre-Yves Chibon ded1fa
        archive_fmt,
Pierre-Yves Chibon ded1fa
    )
Pierre-Yves Chibon ded1fa
Pierre-Yves Chibon ded1fa
    pagure.lib.git.generate_archive(project, commit, tag, name, archive_fmt)
Pierre-Yves Chibon ded1fa
Pierre-Yves Chibon ded1fa
    if archive_fmt == "gzip":
Pierre-Yves Chibon ded1fa
        endpoint = "ui_ns.get_project_archive_gzip"
Pierre-Yves Chibon ded1fa
    elif archive_fmt == "tar":
Pierre-Yves Chibon ded1fa
        endpoint = "ui_ns.get_project_archive_tar"
Pierre-Yves Chibon ded1fa
    else:
Pierre-Yves Chibon ded1fa
        endpoint = "ui_ns.get_project_archive_tar_gz"
Pierre-Yves Chibon ded1fa
    return ret(
Pierre-Yves Chibon ded1fa
        endpoint,
Pierre-Yves Chibon ded1fa
        repo=project.name,
Pierre-Yves Chibon ded1fa
        ref=commit,
Pierre-Yves Chibon ded1fa
        name=name,
Pierre-Yves Chibon ded1fa
        namespace=project.namespace,
Pierre-Yves Chibon ded1fa
        username=project.user.user if project.is_fork else None,
Pierre-Yves Chibon ded1fa
    )