Mercurial > public > mercurial-scm > hg
comparison mercurial/branchmap.py @ 18120:88990d3e3d75
branchmap: extract _updatebranchcache from repo
author | Pierre-Yves David <pierre-yves.david@logilab.fr> |
---|---|
date | Wed, 19 Dec 2012 14:49:06 +0100 |
parents | e70ff1e599f4 |
children | f8a13f061a8a |
comparison
equal
deleted
inserted
replaced
18119:5264464b5f68 | 18120:88990d3e3d75 |
---|---|
48 for node in nodes: | 48 for node in nodes: |
49 f.write("%s %s\n" % (hex(node), encoding.fromlocal(label))) | 49 f.write("%s %s\n" % (hex(node), encoding.fromlocal(label))) |
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 |