topic: add a simple option to reject publishing
authorPierre-Yves David <pierre-yves.david@octobus.net>
Mon, 27 May 2019 03:42:35 +0200
changeset 4647 228caeb8b7af
parent 4646 7b986968700b
child 4648 493470e7a0f2
topic: add a simple option to reject publishing The option is pretty basic but it can be used as base to build larger feature. The main target for going in this direction is to be able to distinct between user that are "simple contributors" pushing topic for review and the "maintainers" or "automation" that can publish changesets.
CHANGELOG
hgext3rd/topic/__init__.py
hgext3rd/topic/flow.py
tests/test-topic-flow-publish-bare.t
tests/test-topic.t
--- a/CHANGELOG	Tue Jun 04 10:07:08 2019 +0200
+++ b/CHANGELOG	Mon May 27 03:42:35 2019 +0200
@@ -17,6 +17,7 @@
     (Make sure your servers are configured to use the obshashrange one.
     It is available in evolve 7.2 and above.)
   * topic: drop the b# alias. It conflicted with normal hashes.
+  * topic: add a `experimental.topic.allow-publish` option (default: True)
 
 8.5.1 -- 2019-04-23
 -------------------
--- a/hgext3rd/topic/__init__.py	Tue Jun 04 10:07:08 2019 +0200
+++ b/hgext3rd/topic/__init__.py	Mon May 27 03:42:35 2019 +0200
@@ -104,6 +104,12 @@
 In addition, the topic extension adds a ``--publish`` flag on :hg:`push`. When
 used, the pushed revisions are published if the push succeeds. It also applies
 to common revisions selected by the push.
+
+One can prevent any publishing to happens in a repository using::
+
+    [experimental]
+    topic.allow-publish = no
+
 """
 
 from __future__ import absolute_import
@@ -205,6 +211,9 @@
     configitem('experimental', 'topic.publish-bare-branch',
                default=False,
     )
+    configitem('experimental', 'topic.allow-publish',
+               default=configitems.dynamicdefault,
+    )
     configitem('_internal', 'keep-topic',
                default=False,
     )
@@ -496,6 +505,23 @@
                     flow.publishbarebranch(repo, tr2)
                     origclose()
                 tr.close = close
+            allow_publish = self.ui.configbool('experimental',
+                                               'topic.allow-publish',
+                                               True)
+            if not allow_publish:
+                if util.safehasattr(tr, 'validator'): # hg <= 4.7
+                    origvalidator = tr.validator
+                else:
+                    origvalidator = tr._validator
+
+                def validator(tr2):
+                    repo = reporef()
+                    flow.reject_publish(repo, tr2)
+                    return origvalidator(tr2)
+                if util.safehasattr(tr, 'validator'): # hg <= 4.7
+                    tr.validator = validator
+                else:
+                    tr._validator = validator
 
             # real transaction start
             ct = self.currenttopic
--- a/hgext3rd/topic/flow.py	Tue Jun 04 10:07:08 2019 +0200
+++ b/hgext3rd/topic/flow.py	Mon May 27 03:42:35 2019 +0200
@@ -55,6 +55,19 @@
         else:
             repo.ui.warn(_("unknown 'topic-mode.server': %s\n" % mode))
 
+def reject_publish(repo, tr):
+    """prevent a transaction to be publish anything"""
+    published = set()
+    for r, (o, n) in tr.changes['phases'].items():
+        if n == phases.public:
+            published.add(r)
+    if published:
+        r = min(published)
+        msg = "rejecting publishing of changeset %s" % repo[r]
+        if len(published) > 1:
+            msg += ' and %d others' % (len(published) - 1)
+        raise error.Abort(msg)
+
 def wrappush(orig, repo, remote, *args, **kwargs):
     """interpret the --publish flag and pass it to the push operation"""
     newargs = kwargs.copy()
--- a/tests/test-topic-flow-publish-bare.t	Tue Jun 04 10:07:08 2019 +0200
+++ b/tests/test-topic-flow-publish-bare.t	Mon May 27 03:42:35 2019 +0200
@@ -294,3 +294,30 @@
   |/
   o  0:ea207398892e ROOT public default
   
+
+Checking the option to prevent publishing
+=========================================
+
+Alone the option is a bit too restrictive to be useful. However combined with
+other tooling or extensions is can become an important permission tool.
+
+  $ hg log -r 'draft()'
+  changeset:   8:858be9a8daaf
+  topic:       bar
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     c_dH0
+  
+  changeset:   10:abb5c84eb9e9
+  topic:       bar
+  parent:      8:858be9a8daaf
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     c_dJ0
+  
+  $ hg phase --public -r 8 --config experimental.topic.allow-publish=no
+  abort: rejecting publishing of changeset 858be9a8daaf
+  [255]
+  $ hg phase --public -r 10 --config experimental.topic.allow-publish=no
+  abort: rejecting publishing of changeset 858be9a8daaf and 1 others
+  [255]
--- a/tests/test-topic.t	Tue Jun 04 10:07:08 2019 +0200
+++ b/tests/test-topic.t	Mon May 27 03:42:35 2019 +0200
@@ -115,6 +115,10 @@
   used, the pushed revisions are published if the push succeeds. It also applies
   to common revisions selected by the push.
   
+  One can prevent any publishing to happens in a repository using
+  
+      [experimental] topic.allow-publish = no
+  
   list of commands:
   
    stack         list all changesets in a topic and other information