mercurial/localrepo.py
changeset 8564 6b9ec23b09fc
parent 8562 e3495c399006
child 8566 744d6322b05b
--- a/mercurial/localrepo.py	Sat May 23 17:03:51 2009 +0200
+++ b/mercurial/localrepo.py	Sat May 23 17:04:31 2009 +0200
@@ -1429,42 +1429,97 @@
         else:
             bases, heads = update, self.changelog.heads()
 
+        def checkbranch(lheads, rheads, updatelh):
+            '''
+            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
+            '''
+
+            warn = 0
+
+            if not revs and len(lheads) > len(rheads):
+                warn = 1
+            else:
+                updatelheads = [self.changelog.heads(x, lheads)
+                                for x in updatelh]
+                newheads = set(sum(updatelheads, [])) & set(lheads)
+
+                if not newheads:
+                    return True
+
+                for r in rheads:
+                    if r in self.changelog.nodemap:
+                        desc = self.changelog.heads(r, heads)
+                        l = [h for h in heads if h in desc]
+                        if not l:
+                            newheads.add(r)
+                    else:
+                        newheads.add(r)
+                if len(newheads) > len(rheads):
+                    warn = 1
+
+            if warn:
+                if not rheads: # new branch requires --force
+                    self.ui.warn(_("abort: push creates new"
+                                   " remote branch '%s'!\n" %
+                                   self[updatelh[0]].branch()))
+                else:
+                    self.ui.warn(_("abort: push creates new remote heads!\n"))
+
+                self.ui.status(_("(did you forget to merge?"
+                                 " use push -f to force)\n"))
+                return False
+            return True
+
         if not bases:
             self.ui.status(_("no changes found\n"))
             return None, 1
         elif not force:
-            # check if we're creating new remote heads
-            # to be a remote head after push, node must be either
+            # 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
+            #
+            # New named branches cannot be created without --force.
 
-            warn = 0
+            if remote_heads != [nullid]:
+                if remote.capable('branchmap'):
+                    localhds = {}
+                    if not revs:
+                        localhds = self.branchmap()
+                    else:
+                        for n in heads:
+                            branch = self[n].branch()
+                            if branch in localhds:
+                                localhds[branch].append(n)
+                            else:
+                                localhds[branch] = [n]
+
+                    remotehds = remote.branchmap()
 
-            if remote_heads == [nullid]:
-                warn = 0
-            elif not revs and len(heads) > len(remote_heads):
-                warn = 1
-            else:
-                newheads = list(heads)
-                for r in remote_heads:
-                    if r in self.changelog.nodemap:
-                        desc = self.changelog.heads(r, heads)
-                        l = [h for h in heads if h in desc]
-                        if not l:
-                            newheads.append(r)
-                    else:
-                        newheads.append(r)
-                if len(newheads) > len(remote_heads):
-                    warn = 1
+                    for lh in localhds:
+                        if lh in remotehds:
+                            rheads = remotehds[lh]
+                        else:
+                            rheads = []
+                        lheads = localhds[lh]
+                        updatelh = [upd for upd in update
+                                    if self[upd].branch() == lh]
+                        if not updatelh:
+                            continue
+                        if not checkbranch(lheads, rheads, updatelh):
+                            return None, 0
+                else:
+                    if not checkbranch(heads, remote_heads, update):
+                        return None, 0
 
-            if warn:
-                self.ui.warn(_("abort: push creates new remote heads!\n"))
-                self.ui.status(_("(did you forget to merge?"
-                                 " use push -f to force)\n"))
-                return None, 0
-            elif inc:
+            if inc:
                 self.ui.warn(_("note: unsynced remote changes!\n"))