mercurial/discovery.py
changeset 17209 5cd3e526ac37
parent 17206 70ebb4bd8083
child 17211 4f321eecbf8d
--- a/mercurial/discovery.py	Mon Jul 16 17:56:50 2012 +0200
+++ b/mercurial/discovery.py	Tue Jul 17 18:21:49 2012 +0200
@@ -149,77 +149,96 @@
 
     return og
 
+def _branchmapsummary(repo, remote, outgoing):
+    """compute a summary of branch and heads status before and after push
+
+    - oldmap:      {'branch': [heads]} mapping for remote
+    - newmap:      {'branch': [heads]} mapping for local
+    - unsynced:    set of branch that have unsynced remote changes
+    - branches:    set of all common branch pushed
+    - newbranches: list of plain new pushed branch
+    """
+    cl = repo.changelog
+
+    # A. Create set of branches involved in the push.
+    branches = set(repo[n].branch() for n in outgoing.missing)
+    remotemap = remote.branchmap()
+    newbranches = branches - set(remotemap)
+    branches.difference_update(newbranches)
+
+    # B. Construct the initial oldmap and newmap dicts.
+    # They contain information about the remote heads before and
+    # after the push, respectively.
+    # Heads not found locally are not included in either dict,
+    # since they won't be affected by the push.
+    # unsynced contains all branches with incoming changesets.
+    oldmap = {}
+    newmap = {}
+    unsynced = set()
+    for branch in branches:
+        remotebrheads = remotemap[branch]
+
+        prunedbrheads = [h for h in remotebrheads if h in cl.nodemap]
+        oldmap[branch] = prunedbrheads
+        newmap[branch] = list(prunedbrheads)
+        if len(remotebrheads) > len(prunedbrheads):
+            unsynced.add(branch)
+
+    # C. Update newmap with outgoing changes.
+    # This will possibly add new heads and remove existing ones.
+    ctxgen = (repo[n] for n in outgoing.missing)
+    repo._updatebranchcache(newmap, ctxgen)
+    return oldmap, newmap, unsynced, branches, newbranches
+
+def _oldbranchmapsummary(repo, remoteheads, outgoing, inc=False):
+    """Compute branchmapsummary for repo without branchmap support"""
+
+    cl = repo.changelog
+    # 1-4b. old servers: Check for new topological heads.
+    # Construct {old,new}map with branch = None (topological branch).
+    # (code based on _updatebranchcache)
+    oldheads = set(h for h in remoteheads if h in cl.nodemap)
+    # all nodes in outgoing.missing are children of either:
+    # - an element of oldheads
+    # - another element of outgoing.missing
+    # - nullrev
+    # This explains why the new head are very simple to compute.
+    r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
+    branches = set([None])
+    newmap = {None: list(c.node() for c in r)}
+    oldmap = {None: oldheads}
+    unsynced = inc and branches or set()
+    return oldmap, newmap, unsynced, branches, set()
+
 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False):
     """Check that a push won't add any outgoing head
 
     raise Abort error and display ui message as needed.
     """
+    # Check for each named branch if we're creating new remote heads.
+    # To be a remote head after push, node must be either:
+    # - unknown locally
+    # - a local outgoing head descended from update
+    # - a remote head that's known locally and not
+    #   ancestral to an outgoing head
     if remoteheads == [nullid]:
         # remote is empty, nothing to check.
         return
 
-    cl = repo.changelog
     if remote.capable('branchmap'):
-        # Check for each named branch if we're creating new remote heads.
-        # To be a remote head after push, node must be either:
-        # - unknown locally
-        # - a local outgoing head descended from update
-        # - a remote head that's known locally and not
-        #   ancestral to an outgoing head
-
-        # 1. Create set of branches involved in the push.
-        branches = set(repo[n].branch() for n in outgoing.missing)
-
-        # 2. Check for new branches on the remote.
-        remotemap = remote.branchmap()
-        newbranches = branches - set(remotemap)
-        if newbranches and not newbranch: # new branch requires --new-branch
-            branchnames = ', '.join(sorted(newbranches))
-            raise util.Abort(_("push creates new remote branches: %s!")
-                               % branchnames,
-                             hint=_("use 'hg push --new-branch' to create"
-                                    " new remote branches"))
-        branches.difference_update(newbranches)
+        bms = _branchmapsummary(repo, remote, outgoing)
+    else:
+        bms = _oldbranchmapsummary(repo, remoteheads, outgoing, inc)
+    oldmap, newmap, unsynced, branches, newbranches = bms
+    # 1. Check for new branches on the remote.
+    if newbranches and not newbranch:  # new branch requires --new-branch
+        branchnames = ', '.join(sorted(newbranches))
+        raise util.Abort(_("push creates new remote branches: %s!")
+                           % branchnames,
+                         hint=_("use 'hg push --new-branch' to create"
+                                " new remote branches"))
 
-        # 3. Construct the initial oldmap and newmap dicts.
-        # They contain information about the remote heads before and
-        # after the push, respectively.
-        # Heads not found locally are not included in either dict,
-        # since they won't be affected by the push.
-        # unsynced contains all branches with incoming changesets.
-        oldmap = {}
-        newmap = {}
-        unsynced = set()
-        for branch in branches:
-            remotebrheads = remotemap[branch]
-            prunedbrheads = [h for h in remotebrheads if h in cl.nodemap]
-            oldmap[branch] = prunedbrheads
-            newmap[branch] = list(prunedbrheads)
-            if len(remotebrheads) > len(prunedbrheads):
-                unsynced.add(branch)
-
-        # 4. Update newmap with outgoing changes.
-        # This will possibly add new heads and remove existing ones.
-        ctxgen = (repo[n] for n in outgoing.missing)
-        repo._updatebranchcache(newmap, ctxgen)
-
-    else:
-        # 1-4b. old servers: Check for new topological heads.
-        # Construct {old,new}map with branch = None (topological branch).
-        # (code based on _updatebranchcache)
-        oldheads = set(h for h in remoteheads if h in cl.nodemap)
-        # all nodes in outgoing.missing are children of either:
-        # - an element of oldheads
-        # - another element of outgoing.missing
-        # - nullrev
-        # This explains why the new head are very simple to compute.
-        r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
-        branches = set([None])
-        newmap = {None: list(c.node() for c in r)}
-        oldmap = {None: oldheads}
-        unsynced = inc and branches or set()
-
-    # 5. Check for new heads.
+    # 2. Check for new heads.
     # If there are more heads after the push than before, a suitable
     # error message, depending on unsynced status, is displayed.
     error = None