##// END OF EJS Templates
prepush: rewrite most of the code from scratch...
Sune Foldager -
r10925:a101a743 stable
parent child Browse files
Show More
@@ -1500,110 +1500,106 b' class localrepository(repo.repository):'
1500 remote_heads = remote.heads()
1500 remote_heads = remote.heads()
1501 inc = self.findincoming(remote, common, remote_heads, force=force)
1501 inc = self.findincoming(remote, common, remote_heads, force=force)
1502
1502
1503 cl = self.changelog
1503 update, updated_heads = self.findoutgoing(remote, common, remote_heads)
1504 update, updated_heads = self.findoutgoing(remote, common, remote_heads)
1504 msng_cl, bases, heads = self.changelog.nodesbetween(update, revs)
1505 outg, bases, heads = cl.nodesbetween(update, revs)
1505
1506 def checkbranch(lheads, rheads, lheadcnt, branchname=None):
1507 '''
1508 check whether there are more local heads than remote heads on
1509 a specific branch.
1510
1511 lheads: local branch heads
1512 rheads: remote branch heads
1513 lheadcnt: total number of local branch heads
1514 '''
1515
1516 warn = 0
1517
1518 if len(lheads) > len(rheads):
1519 warn = 1
1520 else:
1521 # add local heads involved in the push
1522 updatelheads = [self.changelog.heads(x, lheads)
1523 for x in update]
1524 newheads = set(sum(updatelheads, [])) & set(lheads)
1525
1526 if not newheads:
1527 return True
1528
1529 # add heads we don't have or that are not involved in the push
1530 for r in rheads:
1531 if r in self.changelog.nodemap:
1532 desc = self.changelog.heads(r, heads)
1533 l = [h for h in heads if h in desc]
1534 if not l:
1535 newheads.add(r)
1536 else:
1537 newheads.add(r)
1538 if len(newheads) > len(rheads):
1539 warn = 1
1540
1541 if warn:
1542 if branchname is not None:
1543 msg = _("abort: push creates new remote heads"
1544 " on branch '%s'!\n") % branchname
1545 else:
1546 msg = _("abort: push creates new remote heads!\n")
1547 self.ui.warn(msg)
1548 if lheadcnt > len(rheads):
1549 self.ui.status(_("(did you forget to merge?"
1550 " use push -f to force)\n"))
1551 else:
1552 self.ui.status(_("(you should pull and merge or"
1553 " use push -f to force)\n"))
1554 return False
1555 return True
1556
1506
1557 if not bases:
1507 if not bases:
1558 self.ui.status(_("no changes found\n"))
1508 self.ui.status(_("no changes found\n"))
1559 return None, 1
1509 return None, 1
1560 elif not force:
1510
1561 # Check for each named branch if we're creating new remote heads.
1511 if not force and remote_heads != [nullid]:
1562 # To be a remote head after push, node must be either:
1512
1563 # - unknown locally
1513 def fail_multiple_heads(unsynced, branch=None):
1564 # - a local outgoing head descended from update
1514 if branch:
1565 # - a remote head that's known locally and not
1515 msg = _("abort: push creates new remote heads"
1566 # ancestral to an outgoing head
1516 " on branch '%s'!\n") % branch
1567 #
1517 else:
1568 # New named branches cannot be created without --force.
1518 msg = _("abort: push creates new remote heads!\n")
1519 self.ui.warn(msg)
1520 if unsynced:
1521 self.ui.status(_("(you should pull and merge or"
1522 " use push -f to force)\n"))
1523 else:
1524 self.ui.status(_("(did you forget to merge?"
1525 " use push -f to force)\n"))
1526 return None, 0
1569
1527
1570 if remote_heads != [nullid]:
1528 if remote.capable('branchmap'):
1571 if remote.capable('branchmap'):
1529 # Check for each named branch if we're creating new remote heads.
1572 remotebrheads = remote.branchmap()
1530 # To be a remote head after push, node must be either:
1531 # - unknown locally
1532 # - a local outgoing head descended from update
1533 # - a remote head that's known locally and not
1534 # ancestral to an outgoing head
1535 #
1536 # New named branches cannot be created without --force.
1537
1538 # 1. Create set of branches involved in the push.
1539 branches = set(self[n].branch() for n in outg)
1540
1541 # 2. Check for new branches on the remote.
1542 remotemap = remote.branchmap()
1543 newbranches = branches - set(remotemap)
1544 if newbranches: # new branch requires --force
1545 branchnames = ', '.join("%s" % b for b in newbranches)
1546 self.ui.warn(_("abort: push creates "
1547 "new remote branches: %s!\n")
1548 % branchnames)
1549 self.ui.status(_("(use 'hg push -f' to force)\n"))
1550 return None, 0
1573
1551
1574 lbrmap = self.branchmap()
1552 # 3. Construct the initial oldmap and newmap dicts.
1575 localbrheads = {}
1553 # They contain information about the remote heads before and
1576 if not revs:
1554 # after the push, respectively.
1577 for br, hds in lbrmap.iteritems():
1555 # Heads not found locally are not included in either dict,
1578 localbrheads[br] = (len(hds), hds)
1556 # since they won't be affected by the push.
1579 else:
1557 # unsynced contains all branches with incoming changesets.
1580 ctxgen = (self[n] for n in msng_cl)
1558 oldmap = {}
1581 self._updatebranchcache(localbrheads, ctxgen)
1559 newmap = {}
1582 for br, hds in localbrheads.iteritems():
1560 unsynced = set()
1583 localbrheads[br] = (len(lbrmap[br]), hds)
1561 for branch in branches:
1562 remoteheads = remotemap[branch]
1563 prunedheads = [h for h in remoteheads if h in cl.nodemap]
1564 oldmap[branch] = prunedheads
1565 newmap[branch] = list(prunedheads)
1566 if len(remoteheads) > len(prunedheads):
1567 unsynced.add(branch)
1568
1569 # 4. Update newmap with outgoing changes.
1570 # This will possibly add new heads and remove existing ones.
1571 ctxgen = (self[n] for n in outg)
1572 self._updatebranchcache(newmap, ctxgen)
1584
1573
1585 newbranches = list(set(localbrheads) - set(remotebrheads))
1574 # 5. Check for new heads.
1586 if newbranches: # new branch requires --force
1575 # If there are more heads after the push than before, a suitable
1587 branchnames = ', '.join("%s" % b for b in newbranches)
1576 # warning, depending on unsynced status, is displayed.
1588 self.ui.warn(_("abort: push creates "
1577 for branch in branches:
1589 "new remote branches: %s!\n")
1578 if len(newmap[branch]) > len(oldmap[branch]):
1590 % branchnames)
1579 return fail_multiple_heads(branch in unsynced, branch)
1591 # propose 'push -b .' in the msg too?
1580
1592 self.ui.status(_("(use 'hg push -f' to force)\n"))
1581 # 6. Check for unsynced changes on involved branches.
1593 return None, 0
1582 if unsynced:
1594 for branch, x in localbrheads.iteritems():
1583 self.ui.warn(_("note: unsynced remote changes!\n"))
1595 if branch in remotebrheads:
1596 headcnt, lheads = x
1597 rheads = remotebrheads[branch]
1598 if not checkbranch(lheads, rheads, headcnt, branch):
1599 return None, 0
1600 else:
1601 if not checkbranch(heads, remote_heads, len(heads)):
1602 return None, 0
1603
1584
1604 if inc:
1585 else:
1605 self.ui.warn(_("note: unsynced remote changes!\n"))
1586 # Old servers: Check for new topological heads.
1606
1587 # Code based on _updatebranchcache.
1588 newheads = set(h for h in remote_heads if h in cl.nodemap)
1589 oldheadcnt = len(newheads)
1590 newheads.update(outg)
1591 if len(newheads) > 1:
1592 for latest in reversed(outg):
1593 if latest not in newheads:
1594 continue
1595 minhrev = min(cl.rev(h) for h in newheads)
1596 reachable = cl.reachable(latest, cl.node(minhrev))
1597 reachable.remove(latest)
1598 newheads.difference_update(reachable)
1599 if len(newheads) > oldheadcnt:
1600 return fail_multiple_heads(inc)
1601 if inc:
1602 self.ui.warn(_("note: unsynced remote changes!\n"))
1607
1603
1608 if revs is None:
1604 if revs is None:
1609 # use the fast path, no race possible on push
1605 # use the fast path, no race possible on push
@@ -298,6 +298,8 b' hg glog -R inner --template "{rev}: {bra'
298 echo %% outgoing
298 echo %% outgoing
299 hg out inner --template "{rev}: {branches} {desc}\n"
299 hg out inner --template "{rev}: {branches} {desc}\n"
300 hg push inner
300 hg push inner
301 hg push inner -r4 -r5
302 hg in inner
301 cd ..
303 cd ..
302
304
303 exit 0
305 exit 0
@@ -211,7 +211,6 b' searching for changes'
211 2: A a2
211 2: A a2
212 pushing to inner
212 pushing to inner
213 searching for changes
213 searching for changes
214 note: unsynced remote changes!
215 adding changesets
214 adding changesets
216 adding manifests
215 adding manifests
217 adding file changes
216 adding file changes
@@ -253,7 +252,6 b' searching for changes'
253 3: A a2
252 3: A a2
254 pushing to inner
253 pushing to inner
255 searching for changes
254 searching for changes
256 note: unsynced remote changes!
257 adding changesets
255 adding changesets
258 adding manifests
256 adding manifests
259 adding file changes
257 adding file changes
@@ -303,3 +301,10 b' pushing to inner'
303 searching for changes
301 searching for changes
304 abort: push creates new remote heads on branch 'A'!
302 abort: push creates new remote heads on branch 'A'!
305 (did you forget to merge? use push -f to force)
303 (did you forget to merge? use push -f to force)
304 pushing to inner
305 searching for changes
306 abort: push creates new remote heads on branch 'A'!
307 (did you forget to merge? use push -f to force)
308 comparing with inner
309 searching for changes
310 no changes found
General Comments 0
You need to be logged in to leave comments. Login now