##// END OF EJS Templates
branchmap: extract _updatebranchcache from repo
Pierre-Yves David -
r18120:88990d3e default
parent child Browse files
Show More
@@ -50,3 +50,64 b' def write(repo, branches, tip, tiprev):'
50 50 f.close()
51 51 except (IOError, OSError):
52 52 pass
53
54 def update(repo, partial, ctxgen):
55 """Given a branchhead cache, partial, that may have extra nodes or be
56 missing heads, and a generator of nodes that are at least a superset of
57 heads missing, this function updates partial to be correct.
58 """
59 # collect new branch entries
60 newbranches = {}
61 for c in ctxgen:
62 newbranches.setdefault(c.branch(), []).append(c.node())
63 # if older branchheads are reachable from new ones, they aren't
64 # really branchheads. Note checking parents is insufficient:
65 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
66 for branch, newnodes in newbranches.iteritems():
67 bheads = partial.setdefault(branch, [])
68 # Remove candidate heads that no longer are in the repo (e.g., as
69 # the result of a strip that just happened). Avoid using 'node in
70 # self' here because that dives down into branchcache code somewhat
71 # recursively.
72 bheadrevs = [repo.changelog.rev(node) for node in bheads
73 if repo.changelog.hasnode(node)]
74 newheadrevs = [repo.changelog.rev(node) for node in newnodes
75 if repo.changelog.hasnode(node)]
76 ctxisnew = bheadrevs and min(newheadrevs) > max(bheadrevs)
77 # Remove duplicates - nodes that are in newheadrevs and are already
78 # in bheadrevs. This can happen if you strip a node whose parent
79 # was already a head (because they're on different branches).
80 bheadrevs = sorted(set(bheadrevs).union(newheadrevs))
81
82 # Starting from tip means fewer passes over reachable. If we know
83 # the new candidates are not ancestors of existing heads, we don't
84 # have to examine ancestors of existing heads
85 if ctxisnew:
86 iterrevs = sorted(newheadrevs)
87 else:
88 iterrevs = list(bheadrevs)
89
90 # This loop prunes out two kinds of heads - heads that are
91 # superseded by a head in newheadrevs, and newheadrevs that are not
92 # heads because an existing head is their descendant.
93 while iterrevs:
94 latest = iterrevs.pop()
95 if latest not in bheadrevs:
96 continue
97 ancestors = set(repo.changelog.ancestors([latest],
98 bheadrevs[0]))
99 if ancestors:
100 bheadrevs = [b for b in bheadrevs if b not in ancestors]
101 partial[branch] = [repo.changelog.node(rev) for rev in bheadrevs]
102
103 # There may be branches that cease to exist when the last commit in the
104 # branch was stripped. This code filters them out. Note that the
105 # branch that ceased to exist may not be in newbranches because
106 # newbranches is the set of candidate heads, which when you strip the
107 # last commit in a branch will be the parent branch.
108 for branch in partial.keys():
109 nodes = [head for head in partial[branch]
110 if repo.changelog.hasnode(head)]
111 if not nodes:
112 del partial[branch]
113
@@ -8,6 +8,7 b''
8 8 from node import nullid, short
9 9 from i18n import _
10 10 import util, setdiscovery, treediscovery, phases, obsolete, bookmarks
11 import branchmap
11 12
12 13 def findcommonincoming(repo, remote, heads=None, force=False):
13 14 """Return a tuple (common, anyincoming, heads) used to identify the common
@@ -194,7 +195,7 b' def _headssummary(repo, remote, outgoing'
194 195 # This will possibly add new heads and remove existing ones.
195 196 newmap = dict((branch, heads[1]) for branch, heads in headssum.iteritems()
196 197 if heads[0] is not None)
197 repo._updatebranchcache(newmap, missingctx)
198 branchmap.update(repo, newmap, missingctx)
198 199 for branch, newheads in newmap.iteritems():
199 200 headssum[branch][1][:] = newheads
200 201 return headssum
@@ -205,7 +206,7 b' def _oldheadssummary(repo, remoteheads, '
205 206 cl = repo.changelog
206 207 # 1-4b. old servers: Check for new topological heads.
207 208 # Construct {old,new}map with branch = None (topological branch).
208 # (code based on _updatebranchcache)
209 # (code based on update)
209 210 oldheads = set(h for h in remoteheads if h in cl.nodemap)
210 211 # all nodes in outgoing.missing are children of either:
211 212 # - an element of oldheads
@@ -682,7 +682,7 b' class localrepository(object):'
682 682 # on disk
683 683 if lrev < catip:
684 684 ctxgen = (self[r] for r in cl.revs(lrev + 1, catip))
685 self._updatebranchcache(partial, ctxgen)
685 branchmap.update(self, partial, ctxgen)
686 686 branchmap.write(self, partial, cl.node(catip), catip)
687 687 lrev = catip
688 688 # If cacheable tip were lower than actual tip, we need to update the
@@ -691,7 +691,7 b' class localrepository(object):'
691 691 tiprev = len(self) - 1
692 692 if lrev < tiprev:
693 693 ctxgen = (self[r] for r in cl.revs(lrev + 1, tiprev))
694 self._updatebranchcache(partial, ctxgen)
694 branchmap.update(self, partial, ctxgen)
695 695 self._branchcache = partial
696 696 self._branchcachetip = tip
697 697
@@ -699,9 +699,9 b' class localrepository(object):'
699 699 '''returns a dictionary {branch: [branchheads]}'''
700 700 if self.changelog.filteredrevs:
701 701 # some changeset are excluded we can't use the cache
702 branchmap = {}
703 self._updatebranchcache(branchmap, (self[r] for r in self))
704 return branchmap
702 bmap = {}
703 branchmap.update(self, bmap, (self[r] for r in self))
704 return bmap
705 705 else:
706 706 self.updatebranchcache()
707 707 return self._branchcache
@@ -730,66 +730,6 b' class localrepository(object):'
730 730 bt[bn] = self._branchtip(heads)
731 731 return bt
732 732
733 def _updatebranchcache(self, partial, ctxgen):
734 """Given a branchhead cache, partial, that may have extra nodes or be
735 missing heads, and a generator of nodes that are at least a superset of
736 heads missing, this function updates partial to be correct.
737 """
738 # collect new branch entries
739 newbranches = {}
740 for c in ctxgen:
741 newbranches.setdefault(c.branch(), []).append(c.node())
742 # if older branchheads are reachable from new ones, they aren't
743 # really branchheads. Note checking parents is insufficient:
744 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
745 for branch, newnodes in newbranches.iteritems():
746 bheads = partial.setdefault(branch, [])
747 # Remove candidate heads that no longer are in the repo (e.g., as
748 # the result of a strip that just happened). Avoid using 'node in
749 # self' here because that dives down into branchcache code somewhat
750 # recursively.
751 bheadrevs = [self.changelog.rev(node) for node in bheads
752 if self.changelog.hasnode(node)]
753 newheadrevs = [self.changelog.rev(node) for node in newnodes
754 if self.changelog.hasnode(node)]
755 ctxisnew = bheadrevs and min(newheadrevs) > max(bheadrevs)
756 # Remove duplicates - nodes that are in newheadrevs and are already
757 # in bheadrevs. This can happen if you strip a node whose parent
758 # was already a head (because they're on different branches).
759 bheadrevs = sorted(set(bheadrevs).union(newheadrevs))
760
761 # Starting from tip means fewer passes over reachable. If we know
762 # the new candidates are not ancestors of existing heads, we don't
763 # have to examine ancestors of existing heads
764 if ctxisnew:
765 iterrevs = sorted(newheadrevs)
766 else:
767 iterrevs = list(bheadrevs)
768
769 # This loop prunes out two kinds of heads - heads that are
770 # superseded by a head in newheadrevs, and newheadrevs that are not
771 # heads because an existing head is their descendant.
772 while iterrevs:
773 latest = iterrevs.pop()
774 if latest not in bheadrevs:
775 continue
776 ancestors = set(self.changelog.ancestors([latest],
777 bheadrevs[0]))
778 if ancestors:
779 bheadrevs = [b for b in bheadrevs if b not in ancestors]
780 partial[branch] = [self.changelog.node(rev) for rev in bheadrevs]
781
782 # There may be branches that cease to exist when the last commit in the
783 # branch was stripped. This code filters them out. Note that the
784 # branch that ceased to exist may not be in newbranches because
785 # newbranches is the set of candidate heads, which when you strip the
786 # last commit in a branch will be the parent branch.
787 for branch in partial.keys():
788 nodes = [head for head in partial[branch]
789 if self.changelog.hasnode(head)]
790 if not nodes:
791 del partial[branch]
792
793 733 def lookup(self, key):
794 734 return self[key].node()
795 735
@@ -1532,7 +1472,7 b' class localrepository(object):'
1532 1472 tiprev = len(self) - 1
1533 1473 ctxgen = (self[node] for node in newheadnodes
1534 1474 if self.changelog.hasnode(node))
1535 self._updatebranchcache(self._branchcache, ctxgen)
1475 branchmap.update(self, self._branchcache, ctxgen)
1536 1476 branchmap.write(self, self._branchcache, self.changelog.tip(),
1537 1477 tiprev)
1538 1478
General Comments 0
You need to be logged in to leave comments. Login now