push: fix subtle bug in prepush logic
A test case demonstrating the bug has been added.
Contributed by Henrik Stuart and Sune Foldager.
--- a/mercurial/localrepo.py Wed Sep 23 15:51:36 2009 +0200
+++ b/mercurial/localrepo.py Wed Sep 23 18:56:09 2009 +0200
@@ -1493,19 +1493,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
@@ -1513,13 +1510,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)
@@ -1535,7 +1534,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"))
@@ -1578,11 +1577,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):
--- a/tests/test-push-warn Wed Sep 23 15:51:36 2009 +0200
+++ b/tests/test-push-warn Wed Sep 23 18:56:09 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
--- a/tests/test-push-warn.out Wed Sep 23 15:51:36 2009 +0200
+++ b/tests/test-push-warn.out Wed Sep 23 18:56:09 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)
+