D6825: contrib: start building a library for simple hooks

2020-01-24 Thread baymax (Baymax, Your Personal Patch-care Companion)
This revision now requires changes to proceed.
baymax added a comment.
baymax requested changes to this revision.


  There seems to have been no activities on this Diff for the past 3 Months.
  
  By policy, we are automatically moving it out of the `need-review` state.
  
  Please, move it back to `need-review` without hesitation if this diff should 
still be discussed.
  
  :baymax:need-review-idle:

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6825/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6825

To: joerg.sonnenberger, #hg-reviewers, baymax
Cc: durin42, indygreg, pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6825: contrib: start building a library for simple hooks

2019-09-09 Thread durin42 (Augie Fackler)
durin42 added a comment.


  I like where this is going, but I wonder if these specific hooks can be 
written without being in-process Python hooks. Reason being that Python hooks 
use the unstable internals of hg and are semi-discouraged if they're avoidable.
  
  Thoughts?
  
  If you do stick with in-process for this, I definitely want a test included 
so we don't regress our own examples. ;)

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6825/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6825

To: joerg.sonnenberger, #hg-reviewers
Cc: durin42, indygreg, pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6825: contrib: start building a library for simple hooks

2019-09-07 Thread indygreg (Gregory Szorc)
indygreg added a comment.


  I think we should go a step further and have some built-in hooks in Mercurial 
itself, like we do extensions. A good first implementation would be to define 
those hooks somewhere where they can be imported, add tests like they are 
standalone hooks. As a follow-up (read: slightly more work), we can define a 
new config syntax for using these hooks. e.g. `builtin:reject_new_heads`.
  
  What do others think?

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6825/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6825

To: joerg.sonnenberger, #hg-reviewers
Cc: indygreg, pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6825: contrib: start building a library for simple hooks

2019-09-07 Thread joerg.sonnenberger (Joerg Sonnenberger)
joerg.sonnenberger updated this revision to Diff 16431.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6825?vs=16430=16431

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6825/new/

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 by 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 the draft phase. 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: pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6825: contrib: start building a library for simple hooks

2019-09-07 Thread pulkit (Pulkit Goyal)
pulkit added a comment.


  Thanks a lot for putting efforts here. I am +1 on this. I haven't looked at 
the code though, will try to review if no one else beats me to it.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6825/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6825

To: joerg.sonnenberger, #hg-reviewers
Cc: pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6825: contrib: start building a library for simple hooks

2019-09-07 Thread joerg.sonnenberger (Joerg Sonnenberger)
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
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel