D6825: contrib: start building a library for simple hooks
joerg.sonnenberger (Joerg Sonnenberger)
phabricator at mercurial-scm.org
Sat Sep 7 12:50:55 UTC 2019
joerg.sonnenberger created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
Many workflows depend on hooks to enforce certain policies, e.g. to
prevent forced pushes. The Mercurial Guide includes some cases and
Google can help finding others, but it can save users a lot of time
if hg itself has a couple of examples for further customization.
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D6825
AFFECTED FILES
contrib/hooks/enforce_draft_commits.py
contrib/hooks/reject_merge_commits.py
contrib/hooks/reject_new_heads.py
CHANGE DETAILS
diff --git a/contrib/hooks/reject_new_heads.py b/contrib/hooks/reject_new_heads.py
new file mode 100644
--- /dev/null
+++ b/contrib/hooks/reject_new_heads.py
@@ -0,0 +1,25 @@
+# This hook checks branches touched new changesets have at most one
+# open head. It can be used to enforce policies for merge-before-push
+# or rebase-before-push. It does not handle pre-existing hydras.
+#
+# Usage:
+# [hooks]
+# pretxnclose.reject_new_heads = python:../reject_new_heads.py:hook
+
+from mercurial import (
+ error,
+)
+from mercurial.i18n import _
+
+def hook(ui, repo, hooktype, node = None, **kwargs):
+ if hooktype != "pretxnclose":
+ raise error.Abort(_('Unsupported hook type %s') % hooktype)
+ ctx = repo.unfiltered()[node]
+ branches = set()
+ for rev in repo.changelog.revs(start=ctx.rev()):
+ rev = repo[rev]
+ branches.add(rev.branch())
+ for branch in branches:
+ if len(repo.revs("head() and not closed() and branch(%s)", branch)) > 1:
+ raise error.Abort(_('Changes on branch "%s" resulted '
+ 'in multiple heads') % branch)
diff --git a/contrib/hooks/reject_merge_commits.py b/contrib/hooks/reject_merge_commits.py
new file mode 100644
--- /dev/null
+++ b/contrib/hooks/reject_merge_commits.py
@@ -0,0 +1,27 @@
+# This hook checks new changesets for merge commits. Merge commits are allowed
+# only between different branches, i.e. merging a feature branch into the main
+# development branch. This can be used to enforce policies for linear commit
+# histories.
+#
+# Usage:
+# [hooks]
+# pretxnchangegroup.reject_merge_commits = python:../reject_merge_commits.py:hook
+
+from mercurial import (
+ error,
+)
+from mercurial.i18n import _
+
+def hook(ui, repo, hooktype, node = None, **kwargs):
+ if hooktype != "pretxnchangegroup":
+ raise error.Abort(_('Unsupported hook type %s'), hooktype)
+
+ ctx = repo.unfiltered()[node]
+ for rev in repo.changelog.revs(start=ctx.rev()):
+ rev = repo[rev]
+ parents = rev.parents()
+ if len(parents) < 2:
+ continue
+ if all(repo[p].branch() == rev.branch() for p in parents):
+ raise error.Abort(_('%s rejected as merge on the same branch. '
+ 'Please consider rebase.') % rev)
diff --git a/contrib/hooks/enforce_draft_commits.py b/contrib/hooks/enforce_draft_commits.py
new file mode 100644
--- /dev/null
+++ b/contrib/hooks/enforce_draft_commits.py
@@ -0,0 +1,25 @@
+# This hook checks that all new changesets are in drafts. This allows
+# enforcing policies for work-in-progress changes in overlay repositories,
+# i.e. a shared hidden repositories with different views for work-in-progress
+# code and public history.
+#
+# Usage:
+# [hooks]
+# pretxnclose-phase.enforce_draft_commits = python:../enforce_draft_commits.py:hook
+
+from mercurial import (
+ error,
+ phases,
+)
+from mercurial.i18n import _
+
+def hook(ui, repo, hooktype, node = None, **kwargs):
+ if hooktype != "pretxnclose-phase":
+ raise error.Abort(_('Unsupported hook type %s'), hooktype)
+ ctx = repo.unfiltered()[node]
+ if kwargs['oldphase']:
+ raise error.Abort(_('Phase change from %s to %s for %s rejected') %
+ (kwargs['oldphase'], kwargs['phase'], ctx))
+ elif kwargs['phase'] != 'draft':
+ raise error.Abort(_('New changeset %s in phase %s rejected') %
+ (ctx, kwargs['phase']))
To: joerg.sonnenberger, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list