1# Copyright 2020 Joerg Sonnenberger <joerg@bec.de>
2#
3# This software may be used and distributed according to the terms of the
4# GNU General Public License version 2 or any later version.
5
6"""reject_new_heads is a hook to check that branches touched by new changesets
7have at most one open head. It can be used to enforce policies for
8merge-before-push or rebase-before-push. It does not handle pre-existing
9hydras.
10
11Usage:
12  [hooks]
13  pretxnclose.reject_new_heads = \
14    python:hgext.hooklib.reject_new_heads.hook
15"""
16
17from __future__ import absolute_import
18
19from mercurial.i18n import _
20from mercurial import (
21    error,
22    pycompat,
23)
24
25
26def hook(ui, repo, hooktype, node=None, **kwargs):
27    if hooktype != b"pretxnclose":
28        raise error.Abort(
29            _(b'Unsupported hook type %r') % pycompat.bytestr(hooktype)
30        )
31    ctx = repo.unfiltered()[node]
32    branches = set()
33    for rev in repo.changelog.revs(start=ctx.rev()):
34        rev = repo[rev]
35        branches.add(rev.branch())
36    for branch in branches:
37        if len(repo.revs("head() and not closed() and branch(%s)", branch)) > 1:
38            raise error.Abort(
39                _(b'Changes on branch %r resulted in multiple heads')
40                % pycompat.bytestr(branch)
41            )
42