[PATCH] push: fix subtle bug in prepush logic

Henrik Stuart hg at hstuart.dk
Wed Sep 23 10:36:42 CDT 2009


# HG changeset patch
# User Sune Foldager <cryo at cyanite.org>
# Date 1253719466 -7200
# Node ID 19b193fc473748af28ebf0ea5471d1d63f721366
# Parent  a15813fae0a8f414228f9da768c235f9d017ebfa
push: fix subtle bug in prepush logic

A test case demonstrating the bug has been added.
Contributed by Henrik Stuart and Sune Foldager.

diff -r a15813fae0a8 -r 19b193fc4737 mercurial/localrepo.py
--- a/mercurial/localrepo.py	Tue Sep 22 13:30:32 2009 +0200
+++ b/mercurial/localrepo.py	Wed Sep 23 17:24:26 2009 +0200
@@ -1468,19 +1468,16 @@
         inc = self.findincoming(remote, common, remote_heads, force=force)
 
         update, updated_heads = self.findoutgoing(remote, common, remote_heads)
-        if revs is not None:
-            msng_cl, bases, heads = self.changelog.nodesbetween(update, revs)
-        else:
-            bases, heads = update, self.changelog.heads()
+        msng_cl, bases, heads = self.changelog.nodesbetween(update, revs)
 
-        def checkbranch(lheads, rheads, updatelh):
+        def checkbranch(lheads, rheads, updatelb):
             '''
             check whether there are more local heads than remote heads on
             a specific branch.
 
             lheads: local branch heads
             rheads: remote branch heads
-            updatelh: outgoing local branch heads
+            updatelb: outgoing local branch bases
             '''
 
             warn = 0
@@ -1488,13 +1485,15 @@
             if not revs and len(lheads) > len(rheads):
                 warn = 1
             else:
+                # add local heads involved in the push
                 updatelheads = [self.changelog.heads(x, lheads)
-                                for x in updatelh]
+                                for x in updatelb]
                 newheads = set(sum(updatelheads, [])) & set(lheads)
 
                 if not newheads:
                     return True
 
+                # add heads we don't have or that are not involved in the push
                 for r in rheads:
                     if r in self.changelog.nodemap:
                         desc = self.changelog.heads(r, heads)
@@ -1510,7 +1509,7 @@
                 if not rheads: # new branch requires --force
                     self.ui.warn(_("abort: push creates new"
                                    " remote branch '%s'!\n") %
-                                   self[updatelh[0]].branch())
+                                   self[updatelb[0]].branch())
                 else:
                     self.ui.warn(_("abort: push creates new remote heads!\n"))
 
@@ -1553,11 +1552,11 @@
                         else:
                             rheads = []
                         lheads = localhds[lh]
-                        updatelh = [upd for upd in update
+                        updatelb = [upd for upd in update
                                     if self[upd].branch() == lh]
-                        if not updatelh:
+                        if not updatelb:
                             continue
-                        if not checkbranch(lheads, rheads, updatelh):
+                        if not checkbranch(lheads, rheads, updatelb):
                             return None, 0
                 else:
                     if not checkbranch(heads, remote_heads, update):
diff -r a15813fae0a8 -r 19b193fc4737 tests/test-push-warn
--- a/tests/test-push-warn	Tue Sep 22 13:30:32 2009 +0200
+++ b/tests/test-push-warn	Wed Sep 23 17:24:26 2009 +0200
@@ -123,4 +123,21 @@
 hg -q ci -d "1000000 0" -m 11
 hg push -r 10 -r 11 ../f; echo $?
 
+echo % checking prepush logic does not allow silently pushing multiple new heads
+cd ..
+hg init g
+echo init > g/init
+hg -R g ci -Am init
+echo a > g/a
+hg -R g ci -Am a
+hg clone g h
+hg -R g up 0
+echo b > g/b
+hg -R g ci -Am b
+hg -R h up 0
+echo c > h/c
+hg -R h ci -Am c
+hg -R h push g
+echo
+
 exit 0
diff -r a15813fae0a8 -r 19b193fc4737 tests/test-push-warn.out
--- a/tests/test-push-warn.out	Tue Sep 22 13:30:32 2009 +0200
+++ b/tests/test-push-warn.out	Wed Sep 23 17:24:26 2009 +0200
@@ -124,3 +124,20 @@
 adding file changes
 added 2 changesets with 2 changes to 1 files
 0
+% checking prepush logic does not allow silently pushing multiple new heads
+abort: repository g already exists!
+adding init
+adding a
+updating working directory
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+adding b
+created new head
+1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+adding c
+created new head
+pushing to g
+searching for changes
+abort: push creates new remote heads!
+(did you forget to merge? use push -f to force)
+


More information about the Mercurial-devel mailing list