topics: fix auto-publish=abort with servers publishing bare branches stable
authorPierre-Yves David <pierre-yves.david@octobus.net>
Mon, 06 Apr 2020 05:05:07 +0200
branchstable
changeset 5266 af9f40236037
parent 5265 151731be7166
child 5267 ba53591d4aab
topics: fix auto-publish=abort with servers publishing bare branches Before this change, servers that automatically publish bare branches were detected as "non publishing" and the check for automatic publishing on push assumed nothing was to be published. Now we signal the server-side config to clients via a new capability so that they can adjust their behavior.
CHANGELOG
hgext3rd/topic/__init__.py
hgext3rd/topic/flow.py
tests/test-topic-flow-publish-bare.t
--- a/CHANGELOG	Sat Mar 21 15:04:18 2020 +0100
+++ b/CHANGELOG	Mon Apr 06 05:05:07 2020 +0200
@@ -1,13 +1,14 @@
 Changelog
 =========
 
-9.3.0 - in progress
+9.3.1 - in progress
 -------------------
 
   * obsexchange: avoid sending too large request to http server
   * obsdiscovery: server no longer aborts with a 500 error if client sends a
     request without obscommon
   * evolve: improved behavior when evolving above the result of a split
+  * topic: fix auto-publish=abort with server that auto-publishes bare branches
 
 9.3.0 -- 2020-03-04
 -------------------
--- a/hgext3rd/topic/__init__.py	Sat Mar 21 15:04:18 2020 +0100
+++ b/hgext3rd/topic/__init__.py	Mon Apr 06 05:05:07 2020 +0200
@@ -140,6 +140,7 @@
     commands,
     context,
     error,
+    exchange,
     extensions,
     hg,
     localrepo,
@@ -380,6 +381,8 @@
     extensions.wrapfunction(context.workingctx, '__init__', wrapinit)
     # Wrap changelog.add to drop empty topic
     extensions.wrapfunction(changelog.changelog, 'add', wrapadd)
+    # Make exchange._checkpublish handle experimental.topic.publish-bare-branch
+    extensions.wrapfunction(exchange, '_checkpublish', flow.replacecheckpublish)
 
     server.setupserver(ui)
 
@@ -401,6 +404,9 @@
         def _restrictcapabilities(self, caps):
             caps = super(topicrepo, self)._restrictcapabilities(caps)
             caps.add(b'topics')
+            if self.ui.configbool(b'experimental',
+                                  b'topic.publish-bare-branch'):
+                caps.add(b'ext-topics-publish=auto')
             return caps
 
         def commit(self, *args, **kwargs):
--- a/hgext3rd/topic/flow.py	Sat Mar 21 15:04:18 2020 +0100
+++ b/hgext3rd/topic/flow.py	Mon Apr 06 05:05:07 2020 +0200
@@ -108,3 +108,57 @@
                             extendpushoperation)
     extensions.wrapfunction(exchange, '_pushdiscoveryphase', wrapphasediscovery)
     exchange.pushdiscoverymapping[b'phase'] = exchange._pushdiscoveryphase
+
+def replacecheckpublish(orig, pushop):
+    listkeys = exchange.listkeys
+    repo = pushop.repo
+    ui = repo.ui
+    behavior = ui.config(b'experimental', b'auto-publish')
+    if pushop.publish or behavior not in (b'warn', b'confirm', b'abort'):
+        return
+
+    # possible modes are:
+    #
+    # none -> nothing is published on push
+    # all  -> everything is published on push
+    # auto -> only changeset without topic are published on push
+    #
+    # Unknown mode is assumed "all" for safety.
+    #
+    # TODO: do a wider brain storming about mode names.
+
+    mode = b'all'
+    remotephases = listkeys(pushop.remote, b'phases')
+    if not remotephases.get(b'publishing', False):
+        mode = b'none'
+        for c in pushop.remote.capabilities():
+            if c.startswith(b'ext-topics-publish'):
+                mode = c.split(b'=', 1)[1]
+                break
+    if mode == b'none':
+        return
+
+    if pushop.revs is None:
+        published = repo.filtered(b'served').revs(b'not public()')
+    else:
+        published = repo.revs(b'::%ln - public()', pushop.revs)
+    if mode == b'auto':
+        published = repo.revs(b'%ld::(%ld - topic())', published, published)
+    if published:
+        if behavior == b'warn':
+            ui.warn(
+                _(b'%i changesets about to be published\n') % len(published)
+            )
+        elif behavior == b'confirm':
+            if ui.promptchoice(
+                _(b'push and publish %i changesets (yn)?$$ &Yes $$ &No')
+                % len(published)
+            ):
+                raise error.Abort(_(b'user quit'))
+        elif behavior == b'abort':
+            msg = _(b'push would publish %i changesets') % len(published)
+            hint = _(
+                b"use --publish or adjust 'experimental.auto-publish'"
+                b" config"
+            )
+            raise error.Abort(msg, hint=hint)
--- a/tests/test-topic-flow-publish-bare.t	Sat Mar 21 15:04:18 2020 +0100
+++ b/tests/test-topic-flow-publish-bare.t	Mon Apr 06 05:05:07 2020 +0200
@@ -321,3 +321,43 @@
   $ hg phase --public -r 10 --config experimental.topic.allow-publish=no
   abort: rejecting publishing of changeset 858be9a8daaf and 1 others
   [255]
+
+Checking the option to prevent automatic publishing
+===================================================
+
+  $ hg up branchA
+  2 files updated, 0 files merged, 5 files removed, 0 files unresolved
+
+Trying to push changeset without topic (would publish them)
+
+  $ mkcommit c_aM0
+  $ hg debugcapabilities $TESTTMP/bare-branch-server | grep topics
+    ext-topics-publish=auto
+    topics
+  $ hg push --config experimental.auto-publish=abort -r .
+  pushing to $TESTTMP/bare-branch-server
+  abort: push would publish 1 changesets
+  (use --publish or adjust 'experimental.auto-publish' config)
+  [255]
+  $ hg push --config experimental.auto-publish=abort -r . --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+Pushing a changeset with topic (not publishing, no warning)
+
+  $ hg topic test-push-protection
+  marked working directory as topic: test-push-protection
+  $ mkcommit c_aL0
+  active topic 'test-push-protection' grew its first changeset
+  (see 'hg help topics' for more information)
+  $ hg push --config experimental.auto-publish=abort -r .
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files