Patchwork [v3] push: warn after pushing draft changesets with tags

login
register
mail settings
Submitter Nathan Goldbaum
Date March 11, 2016, 5:53 p.m.
Message ID <b1d22b6387f66b3d0400.1457718818@ROUS2>
Download mbox | patch
Permalink /patch/13805/
State Deferred
Headers show

Comments

Nathan Goldbaum - March 11, 2016, 5:53 p.m.
# HG changeset patch
# User Nathan Goldbaum <ngoldbau@illinois.edu>
# Date 1457664319 21600
#      Thu Mar 10 20:45:19 2016 -0600
# Node ID b1d22b6387f66b3d0400a4265e01de8c7f4356b2
# Parent  88738948f5d27cebe673ceb655c6161c34efda7d
push: warn after pushing draft changesets with tags

Tagging a changeset often marks an intention to publish code. For
example, when doing a release. However, if the tagged change is pushed
to a non-publishing repository, it will remain in draft phase, making it
legal to rewrite the tagged change. This may go against a naive
expectation that tagging a commit marks it as public.

This adds a new warning message to notify that a tagged change is still
draft after pushing and offers a suggestion to manually publish the
change and push again.

Patch

diff -r 88738948f5d2 -r b1d22b6387f6 mercurial/commands.py
--- a/mercurial/commands.py	Fri Mar 11 13:00:20 2016 +0000
+++ b/mercurial/commands.py	Thu Mar 10 20:45:19 2016 -0600
@@ -5865,6 +5865,26 @@  def push(ui, repo, dest=None, **opts):
         elif not result and pushop.bkresult:
             result = 2
 
+    # warn if any draft changesets with tags were pushed
+    if not result:
+        tag_and_draft = "(%ln - public()) and tagged()"
+        warned = False
+        for rev in repo.revs(tag_and_draft, pushop.outgoing.missing):
+            ctx = repo[rev]
+            tag_names = ctx.tags()
+            if 'tip' in tag_names:
+                tag_names.remove('tip')
+            if tag_names and ctx.phase() == phases.draft:
+                tag_warning = '"%s"' % tag_names[0]
+                ntags = len(tag_names)
+                if ntags > 1:
+                    tag_warning += ' and %s other tags' % (ntags - 1)
+                warned = True
+                ui.warn(_('pushed tags %s as draft\n') % tag_warning)
+        if warned:
+            ui.warn(_('(use "hg phase --public" and push again to publish '
+                      'the tags)\n'))
+
     return result
 
 @command('recover', [])
diff -r 88738948f5d2 -r b1d22b6387f6 tests/test-push-warn.t
--- a/tests/test-push-warn.t	Fri Mar 11 13:00:20 2016 +0000
+++ b/tests/test-push-warn.t	Thu Mar 10 20:45:19 2016 -0600
@@ -88,6 +88,24 @@  Specifying a revset that evaluates to nu
   adding file changes
   added 2 changesets with 1 changes to 1 files
 
+Warn about pushing a draft, tagged changeset to a non-publishing repository
+
+  $ echo "[phases]" >> ../a/.hg/hgrc
+  $ echo "publish = False" >> ../a/.hg/hgrc
+  $ echo "foobar" > t5
+  $ hg add t5
+  $ hg commit -m "5"
+  $ hg tag tag-name
+  $ hg push ../a
+  pushing to ../a
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+  pushed tags "tag-name" as draft
+  (use "hg phase --public" and push again to publish the tags)
+
   $ cd ..
 
   $ hg init c