Blame pagure/hooks/pagure_force_commit.py

Pierre-Yves Chibon 200af3
# -*- coding: utf-8 -*-
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
"""
Pierre-Yves Chibon 200af3
 (c) 2016 - Copyright Red Hat Inc
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
 Authors:
Pierre-Yves Chibon 200af3
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
"""
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 67d1cc
from __future__ import unicode_literals, absolute_import
Aurélien Bompard dcf6f6
Pierre-Yves Chibon 200af3
import sqlalchemy as sa
Pierre-Yves Chibon 200af3
import wtforms
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 5a5352
try:
Pierre-Yves Chibon 2011e2
    from flask_wtf import FlaskForm
Pierre-Yves Chibon 2011e2
except ImportError:
Pierre-Yves Chibon 5a5352
    from flask_wtf import Form as FlaskForm
Pierre-Yves Chibon 200af3
from sqlalchemy.orm import relation
Pierre-Yves Chibon 200af3
from sqlalchemy.orm import backref
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon fee3d8
import pagure.lib.git
Pierre-Yves Chibon fee3d8
from pagure.hooks import BaseHook, BaseRunner, RequiredIf
Pierre-Yves Chibon 200af3
from pagure.lib.model import BASE, Project
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
class PagureForceCommitTable(BASE):
Pierre-Yves Chibon 200af3
    """ Stores information about the pagure hook deployed on a project.
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
    Table -- hook_pagure_force_commit
Pierre-Yves Chibon 200af3
    """
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 9c2953
    __tablename__ = "hook_pagure_force_commit"
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
    id = sa.Column(sa.Integer, primary_key=True)
Pierre-Yves Chibon 200af3
    project_id = sa.Column(
Pierre-Yves Chibon 200af3
        sa.Integer,
Pierre-Yves Chibon 9c2953
        sa.ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"),
Pierre-Yves Chibon 200af3
        nullable=False,
Pierre-Yves Chibon 200af3
        unique=True,
Pierre-Yves Chibon 9c2953
        index=True,
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
    branches = sa.Column(sa.Text, nullable=False)
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
    active = sa.Column(sa.Boolean, nullable=False, default=False)
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
    project = relation(
Pierre-Yves Chibon 9c2953
        "Project",
Pierre-Yves Chibon 9c2953
        foreign_keys=[project_id],
Pierre-Yves Chibon 9c2953
        remote_side=[Project.id],
Pierre-Yves Chibon 200af3
        backref=backref(
Pierre-Yves Chibon 9c2953
            "pagure_force_commit_hook",
Pierre-Yves Chibon 9c2953
            cascade="delete, delete-orphan",
Pierre-Yves Chibon 9c2953
            single_parent=True,
Pierre-Yves Chibon 9c2953
            uselist=False,
Pierre-Yves Chibon 9c2953
        ),
Pierre-Yves Chibon 200af3
    )
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon fee3d8
class PagureForceCommitRunner(BaseRunner):
Pierre-Yves Chibon fee3d8
    """ Runner for the hook blocking force push. """
Pierre-Yves Chibon fee3d8
Pierre-Yves Chibon fee3d8
    @staticmethod
Pierre-Yves Chibon fee3d8
    def pre_receive(session, username, project, repotype, repodir, changes):
Pierre-Yves Chibon fee3d8
        """ Run the pre-receive tasks of a hook.
Pierre-Yves Chibon fee3d8
Pierre-Yves Chibon fee3d8
        For args, see BaseRunner.runhook.
Pierre-Yves Chibon fee3d8
        """
Pierre-Yves Chibon fee3d8
Pierre-Yves Chibon fee3d8
        # Get the list of branches
Pierre-Yves Chibon fee3d8
        branches = []
Pierre-Yves Chibon fee3d8
        if project.pagure_force_commit_hook:
Pierre-Yves Chibon fee3d8
            branches = [
Pierre-Yves Chibon fee3d8
                branch.strip()
Pierre-Yves Chibon fee3d8
                for branch in project.pagure_force_commit_hook.branches.split(
Pierre-Yves Chibon fee3d8
                    ","
Pierre-Yves Chibon fee3d8
                )
Pierre-Yves Chibon fee3d8
                if branch.strip()
Pierre-Yves Chibon fee3d8
            ]
Pierre-Yves Chibon fee3d8
Pierre-Yves Chibon fee3d8
        for refname in changes:
Pierre-Yves Chibon fee3d8
            (oldrev, newrev) = changes[refname]
Pierre-Yves Chibon fee3d8
Pierre-Yves Chibon fee3d8
            refname = refname.replace("refs/heads/", "")
Pierre-Yves Chibon fee3d8
            if refname in branches or branches == ["*"]:
Pierre-Yves Chibon fee3d8
Pierre-Yves Chibon fee3d8
                if set(newrev) == set(["0"]):
Patrick Uiterwijk e3347b
                    raise Exception("Deletion is forbidden")
Pierre-Yves Chibon fee3d8
                elif pagure.lib.git.is_forced_push(oldrev, newrev, repodir):
Patrick Uiterwijk e3347b
                    raise Exception("Non fast-forward push is forbidden")
Pierre-Yves Chibon fee3d8
Pierre-Yves Chibon fee3d8
Pierre-Yves Chibon 5a5352
class PagureForceCommitForm(FlaskForm):
Pierre-Yves Chibon 9c2953
    """ Form to configure the pagure hook. """
Pierre-Yves Chibon 200af3
Lenka Segura 643d50
    branches = wtforms.StringField("Branches", [RequiredIf("active")])
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 9c2953
    active = wtforms.BooleanField("Active", [wtforms.validators.Optional()])
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 200af3
Pierre-Yves Chibon 9c2953
class PagureForceCommitHook(BaseHook):
Pierre-Yves Chibon 9c2953
    """ PagurPagureForceCommit hook. """
Pierre-Yves Chibon 9c2953
Pierre-Yves Chibon 9c2953
    name = "Block non fast-forward pushes"
Pierre-Yves Chibon 9c2953
    description = (
Pierre-Yves Chibon 9c2953
        "Using this hook you can block any non-fast-forward "
Pierre-Yves Chibon 9c2953
        "commit forced pushed to one or more branches.\n"
Pierre-Yves Chibon 9c2953
        "You can specify one or more branch names (sperated them using "
Pierre-Yves Chibon 9c2953
        "commas) or block all the branches by specifying: ``*``"
Pierre-Yves Chibon 9c2953
    )
Pierre-Yves Chibon 200af3
    form = PagureForceCommitForm
Pierre-Yves Chibon 200af3
    db_object = PagureForceCommitTable
Pierre-Yves Chibon 9c2953
    backref = "pagure_force_commit_hook"
Pierre-Yves Chibon 9c2953
    form_fields = ["branches", "active"]
Pierre-Yves Chibon 9c2953
    hook_type = "pre-receive"
Pierre-Yves Chibon fee3d8
    runner = PagureForceCommitRunner