mercurial/branchmap.py
changeset 18131 f0eeb9b3444a
parent 18130 1b05ffce47bd
child 18132 db25bf1dc828
--- a/mercurial/branchmap.py	Mon Dec 24 02:22:04 2012 +0100
+++ b/mercurial/branchmap.py	Sat Dec 22 17:08:15 2012 +0100
@@ -42,87 +42,6 @@
         partial = branchcache()
     return partial
 
-def update(repo, partial, ctxgen):
-    """Given a branchhead cache, partial, that may have extra nodes or be
-    missing heads, and a generator of nodes that are at least a superset of
-    heads missing, this function updates partial to be correct.
-    """
-    cl = repo.changelog
-    # collect new branch entries
-    newbranches = {}
-    for c in ctxgen:
-        newbranches.setdefault(c.branch(), []).append(c.node())
-    # if older branchheads are reachable from new ones, they aren't
-    # really branchheads. Note checking parents is insufficient:
-    # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
-    for branch, newnodes in newbranches.iteritems():
-        bheads = partial.setdefault(branch, [])
-        # Remove candidate heads that no longer are in the repo (e.g., as
-        # the result of a strip that just happened).  Avoid using 'node in
-        # self' here because that dives down into branchcache code somewhat
-        # recursively.
-        bheadrevs = [cl.rev(node) for node in bheads
-                     if cl.hasnode(node)]
-        newheadrevs = [cl.rev(node) for node in newnodes
-                       if cl.hasnode(node)]
-        ctxisnew = bheadrevs and min(newheadrevs) > max(bheadrevs)
-        # Remove duplicates - nodes that are in newheadrevs and are already
-        # in bheadrevs.  This can happen if you strip a node whose parent
-        # was already a head (because they're on different branches).
-        bheadrevs = sorted(set(bheadrevs).union(newheadrevs))
-
-        # Starting from tip means fewer passes over reachable.  If we know
-        # the new candidates are not ancestors of existing heads, we don't
-        # have to examine ancestors of existing heads
-        if ctxisnew:
-            iterrevs = sorted(newheadrevs)
-        else:
-            iterrevs = list(bheadrevs)
-
-        # This loop prunes out two kinds of heads - heads that are
-        # superseded by a head in newheadrevs, and newheadrevs that are not
-        # heads because an existing head is their descendant.
-        while iterrevs:
-            latest = iterrevs.pop()
-            if latest not in bheadrevs:
-                continue
-            ancestors = set(cl.ancestors([latest],
-                                                     bheadrevs[0]))
-            if ancestors:
-                bheadrevs = [b for b in bheadrevs if b not in ancestors]
-        partial[branch] = [cl.node(rev) for rev in bheadrevs]
-        tiprev = max(bheadrevs)
-        if tiprev > partial.tiprev:
-            partial.tipnode = cl.node(tiprev)
-            partial.tiprev = tiprev
-
-
-    # There may be branches that cease to exist when the last commit in the
-    # branch was stripped.  This code filters them out.  Note that the
-    # branch that ceased to exist may not be in newbranches because
-    # newbranches is the set of candidate heads, which when you strip the
-    # last commit in a branch will be the parent branch.
-    droppednodes = []
-    for branch in partial.keys():
-        nodes = [head for head in partial[branch]
-                 if cl.hasnode(head)]
-        if not nodes:
-            droppednodes.extend(nodes)
-            del partial[branch]
-    try:
-        node = cl.node(partial.tiprev)
-    except IndexError:
-        node = None
-    if ((partial.tipnode != node)
-        or (partial.tipnode in droppednodes)):
-        # cache key are not valid anymore
-        partial.tipnode = nullid
-        partial.tiprev = nullrev
-        for heads in partial.values():
-            tiprev = max(cl.rev(node) for node in heads)
-            if tiprev > partial.tiprev:
-                partial.tipnode = cl.node(tiprev)
-                partial.tiprev = tiprev
 
 
 def updatecache(repo):
@@ -142,7 +61,7 @@
     #                             write on disk
     if partial.tiprev < catip:
         ctxgen = (repo[r] for r in cl.revs(partial.tiprev + 1, catip))
-        update(repo, partial, ctxgen)
+        partial.update(repo, ctxgen)
         partial.write(repo)
     # If cacheable tip were lower than actual tip, we need to update the
     # cache up to tip. This update (from cacheable to actual tip) is not
@@ -150,7 +69,7 @@
     tiprev = len(repo) - 1
     if partial.tiprev < tiprev:
         ctxgen = (repo[r] for r in cl.revs(partial.tiprev + 1, tiprev))
-        update(repo, partial, ctxgen)
+        partial.update(repo, ctxgen)
     repo._branchcache = partial
 
 class branchcache(dict):
@@ -171,3 +90,84 @@
             f.close()
         except (IOError, OSError):
             pass
+
+    def update(self, repo, ctxgen):
+        """Given a branchhead cache, self, that may have extra nodes or be
+        missing heads, and a generator of nodes that are at least a superset of
+        heads missing, this function updates self to be correct.
+        """
+        cl = repo.changelog
+        # collect new branch entries
+        newbranches = {}
+        for c in ctxgen:
+            newbranches.setdefault(c.branch(), []).append(c.node())
+        # if older branchheads are reachable from new ones, they aren't
+        # really branchheads. Note checking parents is insufficient:
+        # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
+        for branch, newnodes in newbranches.iteritems():
+            bheads = self.setdefault(branch, [])
+            # Remove candidate heads that no longer are in the repo (e.g., as
+            # the result of a strip that just happened).  Avoid using 'node in
+            # self' here because that dives down into branchcache code somewhat
+            # recursively.
+            bheadrevs = [cl.rev(node) for node in bheads
+                         if cl.hasnode(node)]
+            newheadrevs = [cl.rev(node) for node in newnodes
+                           if cl.hasnode(node)]
+            ctxisnew = bheadrevs and min(newheadrevs) > max(bheadrevs)
+            # Remove duplicates - nodes that are in newheadrevs and are already
+            # in bheadrevs.  This can happen if you strip a node whose parent
+            # was already a head (because they're on different branches).
+            bheadrevs = sorted(set(bheadrevs).union(newheadrevs))
+
+            # Starting from tip means fewer passes over reachable.  If we know
+            # the new candidates are not ancestors of existing heads, we don't
+            # have to examine ancestors of existing heads
+            if ctxisnew:
+                iterrevs = sorted(newheadrevs)
+            else:
+                iterrevs = list(bheadrevs)
+
+            # This loop prunes out two kinds of heads - heads that are
+            # superseded by a head in newheadrevs, and newheadrevs that are not
+            # heads because an existing head is their descendant.
+            while iterrevs:
+                latest = iterrevs.pop()
+                if latest not in bheadrevs:
+                    continue
+                ancestors = set(cl.ancestors([latest],
+                                                         bheadrevs[0]))
+                if ancestors:
+                    bheadrevs = [b for b in bheadrevs if b not in ancestors]
+            self[branch] = [cl.node(rev) for rev in bheadrevs]
+            tiprev = max(bheadrevs)
+            if tiprev > self.tiprev:
+                self.tipnode = cl.node(tiprev)
+                self.tiprev = tiprev
+
+        # There may be branches that cease to exist when the last commit in the
+        # branch was stripped.  This code filters them out.  Note that the
+        # branch that ceased to exist may not be in newbranches because
+        # newbranches is the set of candidate heads, which when you strip the
+        # last commit in a branch will be the parent branch.
+        droppednodes = []
+        for branch in self.keys():
+            nodes = [head for head in self[branch]
+                     if cl.hasnode(head)]
+            if not nodes:
+                droppednodes.extend(nodes)
+                del self[branch]
+        try:
+            node = cl.node(self.tiprev)
+        except IndexError:
+            node = None
+        if ((self.tipnode != node)
+            or (self.tipnode in droppednodes)):
+            # cache key are not valid anymore
+            self.tipnode = nullid
+            self.tiprev = nullrev
+            for heads in self.values():
+                tiprev = max(cl.rev(node) for node in heads)
+                if tiprev > self.tiprev:
+                    self.tipnode = cl.node(tiprev)
+                    self.tiprev = tiprev