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 |
|
|
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 |
|
|
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