changeset 40767:33d30fb1e4ae

push: config option to control behavior when pushing to a publishing server Pushing to a publishing server by mistake can lead to a difficult situation to solve because evolution doesn't work on public changesets. This new experimental config tries to help avoiding unintentionally (or at least being aware of) pushing to publishing remotes. `hg push --publish` can be used to make push succeed even when auto-publish is set to 'abort'.
author Anton Shestakov <av6@dwimlabs.net>
date Mon, 05 Nov 2018 13:52:19 +0800
parents 773572e5cba2
children f723014677a5
files mercurial/configitems.py mercurial/exchange.py tests/test-phases-exchange.t
diffstat 3 files changed, 99 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/configitems.py	Fri Nov 30 17:42:55 2018 +0300
+++ b/mercurial/configitems.py	Mon Nov 05 13:52:19 2018 +0800
@@ -449,6 +449,9 @@
 coreconfigitem('experimental', 'archivemetatemplate',
     default=dynamicdefault,
 )
+coreconfigitem('experimental', 'auto-publish',
+    default='publish',
+)
 coreconfigitem('experimental', 'bundle-phases',
     default=False,
 )
--- a/mercurial/exchange.py	Fri Nov 30 17:42:55 2018 +0300
+++ b/mercurial/exchange.py	Mon Nov 05 13:52:19 2018 +0800
@@ -334,6 +334,34 @@
         heads = cl.heads()
     return discovery.outgoing(repo, common, heads)
 
+def _checkpublish(pushop):
+    repo = pushop.repo
+    ui = repo.ui
+    behavior = ui.config('experimental', 'auto-publish')
+    if pushop.publish or behavior not in ('warn', 'confirm', 'abort'):
+        return
+    remotephases = listkeys(pushop.remote, 'phases')
+    if not remotephases.get('publishing', False):
+        return
+
+    if pushop.revs is None:
+        published = repo.filtered('served').revs('not public()')
+    else:
+        published = repo.revs('::%ln - public()', pushop.revs)
+    if published:
+        if behavior == 'warn':
+            ui.warn(_('%i changesets about to be published\n')
+                    % len(published))
+        elif behavior == 'confirm':
+            if ui.promptchoice(_('push and publish %i changesets (yn)?'
+                                 '$$ &Yes $$ &No') % len(published)):
+                raise error.Abort(_('user quit'))
+        elif behavior == 'abort':
+            msg = _('push would publish %i changesets') % len(published)
+            hint = _("use --publish or adjust 'experimental.auto-publish'"
+                     " config")
+            raise error.Abort(msg, hint=hint)
+
 def _forcebundle1(op):
     """return true if a pull/push must use bundle1
 
@@ -533,6 +561,7 @@
             lock or util.nullcontextmanager(), \
             pushop.trmanager or util.nullcontextmanager():
         pushop.repo.checkpush(pushop)
+        _checkpublish(pushop)
         _pushdiscovery(pushop)
         if not _forcebundle1(pushop):
             _pushbundle2(pushop)
--- a/tests/test-phases-exchange.t	Fri Nov 30 17:42:55 2018 +0300
+++ b/tests/test-phases-exchange.t	Mon Nov 05 13:52:19 2018 +0800
@@ -1562,6 +1562,73 @@
   $ killdaemons.py
 
 
+auto-publish config
+-------------------
+
+  $ hg init auto-publish-orig
+  $ hg clone -q auto-publish-orig auto-publish-clone
+  $ cd auto-publish-clone
+  $ mkcommit a-p-A
+  test-debug-phase: new rev 0:  x -> 1
+  $ mkcommit a-p-B
+  test-debug-phase: new rev 1:  x -> 1
+
+abort behavior
+
+  $ hg push --config experimental.auto-publish=abort
+  pushing to $TESTTMP/auto-publish-orig
+  abort: push would publish 2 changesets
+  (use --publish or adjust 'experimental.auto-publish' config)
+  [255]
+  $ hg push -r '.^' --config experimental.auto-publish=abort
+  pushing to $TESTTMP/auto-publish-orig
+  abort: push would publish 1 changesets
+  (use --publish or adjust 'experimental.auto-publish' config)
+  [255]
+
+--publish flag makes push succeed
+
+  $ hg push -r '.^' --publish --config experimental.auto-publish=abort
+  pushing to $TESTTMP/auto-publish-orig
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  test-debug-phase: new rev 0:  x -> 0
+  test-debug-phase: move rev 0: 1 -> 0
+
+warn behavior
+
+  $ hg push --config experimental.auto-publish=warn
+  pushing to $TESTTMP/auto-publish-orig
+  1 changesets about to be published
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  test-debug-phase: new rev 1:  x -> 0
+  test-debug-phase: move rev 1: 1 -> 0
+
+confirm behavior
+
+  $ mkcommit a-p-C
+  test-debug-phase: new rev 2:  x -> 1
+  $ hg push --config experimental.auto-publish=confirm
+  pushing to $TESTTMP/auto-publish-orig
+  push and publish 1 changesets (yn)? y
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  test-debug-phase: new rev 2:  x -> 0
+  test-debug-phase: move rev 2: 1 -> 0
+
+  $ cd ..
+
+
 --publish flag
 --------------