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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
b |
|
|
703 |
self |
|
|
704 |
return b |
|
|
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 |
|
|
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