Show More
@@ -50,3 +50,64 b' def write(repo, branches, tip, tiprev):' | |||||
50 | f.close() |
|
50 | f.close() | |
51 | except (IOError, OSError): |
|
51 | except (IOError, OSError): | |
52 | pass |
|
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 | from node import nullid, short |
|
8 | from node import nullid, short | |
9 | from i18n import _ |
|
9 | from i18n import _ | |
10 | import util, setdiscovery, treediscovery, phases, obsolete, bookmarks |
|
10 | import util, setdiscovery, treediscovery, phases, obsolete, bookmarks | |
|
11 | import branchmap | |||
11 |
|
12 | |||
12 | def findcommonincoming(repo, remote, heads=None, force=False): |
|
13 | def findcommonincoming(repo, remote, heads=None, force=False): | |
13 | """Return a tuple (common, anyincoming, heads) used to identify the common |
|
14 | """Return a tuple (common, anyincoming, heads) used to identify the common | |
@@ -194,7 +195,7 b' def _headssummary(repo, remote, outgoing' | |||||
194 | # This will possibly add new heads and remove existing ones. |
|
195 | # This will possibly add new heads and remove existing ones. | |
195 | newmap = dict((branch, heads[1]) for branch, heads in headssum.iteritems() |
|
196 | newmap = dict((branch, heads[1]) for branch, heads in headssum.iteritems() | |
196 | if heads[0] is not None) |
|
197 | if heads[0] is not None) | |
197 |
repo |
|
198 | branchmap.update(repo, newmap, missingctx) | |
198 | for branch, newheads in newmap.iteritems(): |
|
199 | for branch, newheads in newmap.iteritems(): | |
199 | headssum[branch][1][:] = newheads |
|
200 | headssum[branch][1][:] = newheads | |
200 | return headssum |
|
201 | return headssum | |
@@ -205,7 +206,7 b' def _oldheadssummary(repo, remoteheads, ' | |||||
205 | cl = repo.changelog |
|
206 | cl = repo.changelog | |
206 | # 1-4b. old servers: Check for new topological heads. |
|
207 | # 1-4b. old servers: Check for new topological heads. | |
207 | # Construct {old,new}map with branch = None (topological branch). |
|
208 | # Construct {old,new}map with branch = None (topological branch). | |
208 |
# (code based on |
|
209 | # (code based on update) | |
209 | oldheads = set(h for h in remoteheads if h in cl.nodemap) |
|
210 | oldheads = set(h for h in remoteheads if h in cl.nodemap) | |
210 | # all nodes in outgoing.missing are children of either: |
|
211 | # all nodes in outgoing.missing are children of either: | |
211 | # - an element of oldheads |
|
212 | # - an element of oldheads |
@@ -682,7 +682,7 b' class localrepository(object):' | |||||
682 | # on disk |
|
682 | # on disk | |
683 | if lrev < catip: |
|
683 | if lrev < catip: | |
684 | ctxgen = (self[r] for r in cl.revs(lrev + 1, catip)) |
|
684 | ctxgen = (self[r] for r in cl.revs(lrev + 1, catip)) | |
685 |
self |
|
685 | branchmap.update(self, partial, ctxgen) | |
686 | branchmap.write(self, partial, cl.node(catip), catip) |
|
686 | branchmap.write(self, partial, cl.node(catip), catip) | |
687 | lrev = catip |
|
687 | lrev = catip | |
688 | # If cacheable tip were lower than actual tip, we need to update the |
|
688 | # If cacheable tip were lower than actual tip, we need to update the | |
@@ -691,7 +691,7 b' class localrepository(object):' | |||||
691 | tiprev = len(self) - 1 |
|
691 | tiprev = len(self) - 1 | |
692 | if lrev < tiprev: |
|
692 | if lrev < tiprev: | |
693 | ctxgen = (self[r] for r in cl.revs(lrev + 1, tiprev)) |
|
693 | ctxgen = (self[r] for r in cl.revs(lrev + 1, tiprev)) | |
694 |
self |
|
694 | branchmap.update(self, partial, ctxgen) | |
695 | self._branchcache = partial |
|
695 | self._branchcache = partial | |
696 | self._branchcachetip = tip |
|
696 | self._branchcachetip = tip | |
697 |
|
697 | |||
@@ -699,9 +699,9 b' class localrepository(object):' | |||||
699 | '''returns a dictionary {branch: [branchheads]}''' |
|
699 | '''returns a dictionary {branch: [branchheads]}''' | |
700 | if self.changelog.filteredrevs: |
|
700 | if self.changelog.filteredrevs: | |
701 | # some changeset are excluded we can't use the cache |
|
701 | # some changeset are excluded we can't use the cache | |
702 |
b |
|
702 | bmap = {} | |
703 |
self |
|
703 | branchmap.update(self, bmap, (self[r] for r in self)) | |
704 |
return b |
|
704 | return bmap | |
705 | else: |
|
705 | else: | |
706 | self.updatebranchcache() |
|
706 | self.updatebranchcache() | |
707 | return self._branchcache |
|
707 | return self._branchcache | |
@@ -730,66 +730,6 b' class localrepository(object):' | |||||
730 | bt[bn] = self._branchtip(heads) |
|
730 | bt[bn] = self._branchtip(heads) | |
731 | return bt |
|
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 | def lookup(self, key): |
|
733 | def lookup(self, key): | |
794 | return self[key].node() |
|
734 | return self[key].node() | |
795 |
|
735 | |||
@@ -1532,7 +1472,7 b' class localrepository(object):' | |||||
1532 | tiprev = len(self) - 1 |
|
1472 | tiprev = len(self) - 1 | |
1533 | ctxgen = (self[node] for node in newheadnodes |
|
1473 | ctxgen = (self[node] for node in newheadnodes | |
1534 | if self.changelog.hasnode(node)) |
|
1474 | if self.changelog.hasnode(node)) | |
1535 |
self |
|
1475 | branchmap.update(self, self._branchcache, ctxgen) | |
1536 | branchmap.write(self, self._branchcache, self.changelog.tip(), |
|
1476 | branchmap.write(self, self._branchcache, self.changelog.tip(), | |
1537 | tiprev) |
|
1477 | tiprev) | |
1538 |
|
1478 |
General Comments 0
You need to be logged in to leave comments.
Login now