Show More
@@ -1500,110 +1500,106 b' class localrepository(repo.repository):' | |||
|
1500 | 1500 | remote_heads = remote.heads() |
|
1501 | 1501 | inc = self.findincoming(remote, common, remote_heads, force=force) |
|
1502 | 1502 | |
|
1503 | cl = self.changelog | |
|
1503 | 1504 | update, updated_heads = self.findoutgoing(remote, common, remote_heads) |
|
1504 |
|
|
|
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 | |
|
1505 | outg, bases, heads = cl.nodesbetween(update, revs) | |
|
1556 | 1506 | |
|
1557 | 1507 | if not bases: |
|
1558 | 1508 | self.ui.status(_("no changes found\n")) |
|
1559 | 1509 | return None, 1 |
|
1560 | elif not force: | |
|
1561 | # Check for each named branch if we're creating new remote heads. | |
|
1562 | # To be a remote head after push, node must be either: | |
|
1563 | # - unknown locally | |
|
1564 | # - a local outgoing head descended from update | |
|
1565 | # - a remote head that's known locally and not | |
|
1566 | # ancestral to an outgoing head | |
|
1567 |
|
|
|
1568 | # New named branches cannot be created without --force. | |
|
1510 | ||
|
1511 | if not force and remote_heads != [nullid]: | |
|
1512 | ||
|
1513 | def fail_multiple_heads(unsynced, branch=None): | |
|
1514 | if branch: | |
|
1515 | msg = _("abort: push creates new remote heads" | |
|
1516 | " on branch '%s'!\n") % branch | |
|
1517 | else: | |
|
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]: | |
|
1571 | if remote.capable('branchmap'): | |
|
1572 | remotebrheads = remote.branchmap() | |
|
1528 | if remote.capable('branchmap'): | |
|
1529 | # Check for each named branch if we're creating new remote heads. | |
|
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() | |
|
1575 | localbrheads = {} | |
|
1576 | if not revs: | |
|
1577 | for br, hds in lbrmap.iteritems(): | |
|
1578 | localbrheads[br] = (len(hds), hds) | |
|
1579 | else: | |
|
1580 | ctxgen = (self[n] for n in msng_cl) | |
|
1581 | self._updatebranchcache(localbrheads, ctxgen) | |
|
1582 | for br, hds in localbrheads.iteritems(): | |
|
1583 | localbrheads[br] = (len(lbrmap[br]), hds) | |
|
1552 | # 3. Construct the initial oldmap and newmap dicts. | |
|
1553 | # They contain information about the remote heads before and | |
|
1554 | # after the push, respectively. | |
|
1555 | # Heads not found locally are not included in either dict, | |
|
1556 | # since they won't be affected by the push. | |
|
1557 | # unsynced contains all branches with incoming changesets. | |
|
1558 | oldmap = {} | |
|
1559 | newmap = {} | |
|
1560 | unsynced = set() | |
|
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)) | |
|
1586 | if newbranches: # new branch requires --force | |
|
1587 | branchnames = ', '.join("%s" % b for b in newbranches) | |
|
1588 | self.ui.warn(_("abort: push creates " | |
|
1589 | "new remote branches: %s!\n") | |
|
1590 | % branchnames) | |
|
1591 | # propose 'push -b .' in the msg too? | |
|
1592 | self.ui.status(_("(use 'hg push -f' to force)\n")) | |
|
1593 | return None, 0 | |
|
1594 | for branch, x in localbrheads.iteritems(): | |
|
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 | |
|
1574 | # 5. Check for new heads. | |
|
1575 | # If there are more heads after the push than before, a suitable | |
|
1576 | # warning, depending on unsynced status, is displayed. | |
|
1577 | for branch in branches: | |
|
1578 | if len(newmap[branch]) > len(oldmap[branch]): | |
|
1579 | return fail_multiple_heads(branch in unsynced, branch) | |
|
1580 | ||
|
1581 | # 6. Check for unsynced changes on involved branches. | |
|
1582 | if unsynced: | |
|
1583 | self.ui.warn(_("note: unsynced remote changes!\n")) | |
|
1603 | 1584 | |
|
1604 |
|
|
|
1605 | self.ui.warn(_("note: unsynced remote changes!\n")) | |
|
1606 | ||
|
1585 | else: | |
|
1586 | # Old servers: Check for new topological heads. | |
|
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 | 1604 | if revs is None: |
|
1609 | 1605 | # use the fast path, no race possible on push |
@@ -298,6 +298,8 b' hg glog -R inner --template "{rev}: {bra' | |||
|
298 | 298 | echo %% outgoing |
|
299 | 299 | hg out inner --template "{rev}: {branches} {desc}\n" |
|
300 | 300 | hg push inner |
|
301 | hg push inner -r4 -r5 | |
|
302 | hg in inner | |
|
301 | 303 | cd .. |
|
302 | 304 | |
|
303 | 305 | exit 0 |
@@ -211,7 +211,6 b' searching for changes' | |||
|
211 | 211 | 2: A a2 |
|
212 | 212 | pushing to inner |
|
213 | 213 | searching for changes |
|
214 | note: unsynced remote changes! | |
|
215 | 214 | adding changesets |
|
216 | 215 | adding manifests |
|
217 | 216 | adding file changes |
@@ -253,7 +252,6 b' searching for changes' | |||
|
253 | 252 | 3: A a2 |
|
254 | 253 | pushing to inner |
|
255 | 254 | searching for changes |
|
256 | note: unsynced remote changes! | |
|
257 | 255 | adding changesets |
|
258 | 256 | adding manifests |
|
259 | 257 | adding file changes |
@@ -303,3 +301,10 b' pushing to inner' | |||
|
303 | 301 | searching for changes |
|
304 | 302 | abort: push creates new remote heads on branch 'A'! |
|
305 | 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