annotate mercurial/branchmap.py @ 18189:b9026ba002f6

branchmap: enable caching for filtered version too The `_branchcache` attribute is turned into a dictionary. Key are filter name and value is a `branchcache` object. Unfiltered version is cached as `None` filter. The attribute is renamed to `_branchcaches` to avoid confusion with the previous one. Both old and new contents are dictionary even if their contents are different. I prefer possible extension code to crash right away instead of just messing the wrong dictionary. As all different caches work isolated to each other, this code keeps the previous behavior of using the unfiltered cache we nothing is filtered. This is a cheap way to have cache collaborate and nullify potential impact in the default case.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Mon, 24 Dec 2012 03:21:15 +0100
parents 46ed5226503a
children 493778b5fe9f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
18116
bcee63733aad branchmap: create a mercurial.branchmap module
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
1 # branchmap.py - logic to computes, maintain and stores branchmap for local repo
bcee63733aad branchmap: create a mercurial.branchmap module
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
2 #
bcee63733aad branchmap: create a mercurial.branchmap module
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
bcee63733aad branchmap: create a mercurial.branchmap module
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
4 #
bcee63733aad branchmap: create a mercurial.branchmap module
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
bcee63733aad branchmap: create a mercurial.branchmap module
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
18117
526e7ec5c96e branchmap: extract write logic from localrepo
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18116
diff changeset
7
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
8 from node import bin, hex, nullid, nullrev
18117
526e7ec5c96e branchmap: extract write logic from localrepo
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18116
diff changeset
9 import encoding
18168
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
10 import util
18117
526e7ec5c96e branchmap: extract write logic from localrepo
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18116
diff changeset
11
18185
5a047276764e branchmap: move the cache file name into a dedicated function
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18184
diff changeset
12 def _filename(repo):
18187
4df8716d32f1 branchmap: use a different file name for filtered view of repo
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18185
diff changeset
13 """name of a branchcache file for a given repo or repoview"""
4df8716d32f1 branchmap: use a different file name for filtered view of repo
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18185
diff changeset
14 filename = "cache/branchheads"
4df8716d32f1 branchmap: use a different file name for filtered view of repo
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18185
diff changeset
15 if repo.filtername:
4df8716d32f1 branchmap: use a different file name for filtered view of repo
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18185
diff changeset
16 filename = '%s-%s' % (filename, repo.filtername)
4df8716d32f1 branchmap: use a different file name for filtered view of repo
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18185
diff changeset
17 return filename
18185
5a047276764e branchmap: move the cache file name into a dedicated function
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18184
diff changeset
18
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
19 def read(repo):
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
20 try:
18185
5a047276764e branchmap: move the cache file name into a dedicated function
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18184
diff changeset
21 f = repo.opener(_filename(repo))
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
22 lines = f.read().split('\n')
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
23 f.close()
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
24 except (IOError, OSError):
18126
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
25 return branchcache()
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
26
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
27 try:
18184
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
28 cachekey = lines.pop(0).split(" ", 2)
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
29 last, lrev = cachekey[:2]
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
30 last, lrev = bin(last), int(lrev)
18184
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
31 filteredhash = None
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
32 if len(cachekey) > 2:
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
33 filteredhash = bin(cachekey[2])
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
34 partial = branchcache(tipnode=last, tiprev=lrev,
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
35 filteredhash=filteredhash)
18132
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
36 if not partial.validfor(repo):
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
37 # invalidate the cache
18166
3a2e810dd3d8 branchmap: improve invalid cache message when reading
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18132
diff changeset
38 raise ValueError('tip differs')
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
39 for l in lines:
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
40 if not l:
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
41 continue
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
42 node, label = l.split(" ", 1)
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
43 label = encoding.tolocal(label.strip())
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
44 if not node in repo:
18166
3a2e810dd3d8 branchmap: improve invalid cache message when reading
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18132
diff changeset
45 raise ValueError('node %s does not exist' % node)
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
46 partial.setdefault(label, []).append(bin(node))
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
47 except KeyboardInterrupt:
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
48 raise
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
49 except Exception, inst:
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
50 if repo.ui.debugflag:
18188
46ed5226503a branchmap: report filtername when read fails
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18187
diff changeset
51 msg = 'invalid branchheads cache'
46ed5226503a branchmap: report filtername when read fails
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18187
diff changeset
52 if repo.filtername is not None:
46ed5226503a branchmap: report filtername when read fails
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18187
diff changeset
53 msg += ' (%s)' % repo.filtername
46ed5226503a branchmap: report filtername when read fails
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18187
diff changeset
54 msg += ': %s\n'
46ed5226503a branchmap: report filtername when read fails
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18187
diff changeset
55 repo.ui.warn(msg % inst)
18126
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
56 partial = branchcache()
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
57 return partial
18118
e70ff1e599f4 branchmap: extract read logic from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18117
diff changeset
58
18130
1b05ffce47bd branchmap: make update responsible to update the cache key
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18129
diff changeset
59
18120
88990d3e3d75 branchmap: extract _updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18118
diff changeset
60
18121
f8a13f061a8a branchmap: extract updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18120
diff changeset
61 def updatecache(repo):
f8a13f061a8a branchmap: extract updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18120
diff changeset
62 cl = repo.changelog
18189
b9026ba002f6 branchmap: enable caching for filtered version too
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18188
diff changeset
63 filtername = repo.filtername
b9026ba002f6 branchmap: enable caching for filtered version too
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18188
diff changeset
64 partial = repo._branchcaches.get(filtername)
18121
f8a13f061a8a branchmap: extract updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18120
diff changeset
65
18132
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
66 if partial is None or not partial.validfor(repo):
18126
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
67 partial = read(repo)
18121
f8a13f061a8a branchmap: extract updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18120
diff changeset
68
f8a13f061a8a branchmap: extract updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18120
diff changeset
69 catip = repo._cacheabletip()
18126
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
70 # if partial.tiprev == catip: cache is already up to date
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
71 # if partial.tiprev > catip: we have uncachable element in `partial` can't
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
72 # write on disk
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
73 if partial.tiprev < catip:
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
74 ctxgen = (repo[r] for r in cl.revs(partial.tiprev + 1, catip))
18131
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
75 partial.update(repo, ctxgen)
18128
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
76 partial.write(repo)
18121
f8a13f061a8a branchmap: extract updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18120
diff changeset
77 # If cacheable tip were lower than actual tip, we need to update the
f8a13f061a8a branchmap: extract updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18120
diff changeset
78 # cache up to tip. This update (from cacheable to actual tip) is not
f8a13f061a8a branchmap: extract updatebranchcache from repo
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18120
diff changeset
79 # written to disk since it's not cacheable.
18167
59ac9a551bf4 branchmap: improve computation of target tip
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18166
diff changeset
80 tiprev = cl.rev(cl.tip())
18126
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
81 if partial.tiprev < tiprev:
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
82 ctxgen = (repo[r] for r in cl.revs(partial.tiprev + 1, tiprev))
18131
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
83 partial.update(repo, ctxgen)
18189
b9026ba002f6 branchmap: enable caching for filtered version too
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18188
diff changeset
84 repo._branchcaches[repo.filtername] = partial
18124
79db6d40bced branchmap: store branchcache in a dedicated object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18121
diff changeset
85
79db6d40bced branchmap: store branchcache in a dedicated object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18121
diff changeset
86 class branchcache(dict):
79db6d40bced branchmap: store branchcache in a dedicated object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18121
diff changeset
87 """A dict like object that hold branches heads cache"""
79db6d40bced branchmap: store branchcache in a dedicated object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18121
diff changeset
88
18168
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
89 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev,
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
90 filteredhash=None):
18125
ad194a8ab5c1 branchmap: add the tipnode (cache key) on the branchcache object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18124
diff changeset
91 super(branchcache, self).__init__(entries)
ad194a8ab5c1 branchmap: add the tipnode (cache key) on the branchcache object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18124
diff changeset
92 self.tipnode = tipnode
18126
090ada0acddb branchmap: add the tiprev (cache key) on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18125
diff changeset
93 self.tiprev = tiprev
18168
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
94 self.filteredhash = filteredhash
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
95
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
96 def _hashfiltered(self, repo):
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
97 """build hash of revision filtered in the current cache
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
98
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
99 Tracking tipnode and tiprev is not enough to ensure validaty of the
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
100 cache as they do not help to distinct cache that ignored various
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
101 revision bellow tiprev.
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
102
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
103 To detect such difference, we build a cache of all ignored revisions.
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
104 """
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
105 cl = repo.changelog
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
106 if not cl.filteredrevs:
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
107 return None
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
108 key = None
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
109 revs = sorted(r for r in cl.filteredrevs if r <= self.tiprev)
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
110 if revs:
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
111 s = util.sha1()
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
112 for rev in revs:
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
113 s.update('%s;' % rev)
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
114 key = s.digest()
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
115 return key
18128
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
116
18132
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
117 def validfor(self, repo):
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
118 """Is the cache content valide regarding a repo
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
119
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
120 - False when cached tipnode are unknown or if we detect a strip.
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
121 - True when cache is up to date or a subset of current repo."""
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
122 try:
18168
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
123 return ((self.tipnode == repo.changelog.node(self.tiprev))
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
124 and (self.filteredhash == self._hashfiltered(repo)))
18132
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
125 except IndexError:
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
126 return False
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
127
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
128
18128
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
129 def write(self, repo):
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
130 try:
18185
5a047276764e branchmap: move the cache file name into a dedicated function
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18184
diff changeset
131 f = repo.opener(_filename(repo), "w", atomictemp=True)
18184
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
132 cachekey = [hex(self.tipnode), str(self.tiprev)]
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
133 if self.filteredhash is not None:
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
134 cachekey.append(hex(self.filteredhash))
8d48af68e2ae branchmap: read and write key part related to filtered revision
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18168
diff changeset
135 f.write(" ".join(cachekey) + '\n')
18128
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
136 for label, nodes in self.iteritems():
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
137 for node in nodes:
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
138 f.write("%s %s\n" % (hex(node), encoding.fromlocal(label)))
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
139 f.close()
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
140 except (IOError, OSError):
f0d56efaa35a branchmap: make write a method on the branchmap object
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18127
diff changeset
141 pass
18131
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
142
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
143 def update(self, repo, ctxgen):
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
144 """Given a branchhead cache, self, that may have extra nodes or be
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
145 missing heads, and a generator of nodes that are at least a superset of
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
146 heads missing, this function updates self to be correct.
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
147 """
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
148 cl = repo.changelog
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
149 # collect new branch entries
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
150 newbranches = {}
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
151 for c in ctxgen:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
152 newbranches.setdefault(c.branch(), []).append(c.node())
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
153 # if older branchheads are reachable from new ones, they aren't
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
154 # really branchheads. Note checking parents is insufficient:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
155 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
156 for branch, newnodes in newbranches.iteritems():
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
157 bheads = self.setdefault(branch, [])
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
158 # Remove candidate heads that no longer are in the repo (e.g., as
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
159 # the result of a strip that just happened). Avoid using 'node in
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
160 # self' here because that dives down into branchcache code somewhat
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
161 # recursively.
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
162 bheadrevs = [cl.rev(node) for node in bheads
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
163 if cl.hasnode(node)]
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
164 newheadrevs = [cl.rev(node) for node in newnodes
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
165 if cl.hasnode(node)]
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
166 ctxisnew = bheadrevs and min(newheadrevs) > max(bheadrevs)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
167 # Remove duplicates - nodes that are in newheadrevs and are already
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
168 # in bheadrevs. This can happen if you strip a node whose parent
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
169 # was already a head (because they're on different branches).
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
170 bheadrevs = sorted(set(bheadrevs).union(newheadrevs))
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
171
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
172 # Starting from tip means fewer passes over reachable. If we know
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
173 # the new candidates are not ancestors of existing heads, we don't
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
174 # have to examine ancestors of existing heads
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
175 if ctxisnew:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
176 iterrevs = sorted(newheadrevs)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
177 else:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
178 iterrevs = list(bheadrevs)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
179
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
180 # This loop prunes out two kinds of heads - heads that are
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
181 # superseded by a head in newheadrevs, and newheadrevs that are not
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
182 # heads because an existing head is their descendant.
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
183 while iterrevs:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
184 latest = iterrevs.pop()
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
185 if latest not in bheadrevs:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
186 continue
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
187 ancestors = set(cl.ancestors([latest],
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
188 bheadrevs[0]))
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
189 if ancestors:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
190 bheadrevs = [b for b in bheadrevs if b not in ancestors]
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
191 self[branch] = [cl.node(rev) for rev in bheadrevs]
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
192 tiprev = max(bheadrevs)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
193 if tiprev > self.tiprev:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
194 self.tipnode = cl.node(tiprev)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
195 self.tiprev = tiprev
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
196
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
197 # There may be branches that cease to exist when the last commit in the
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
198 # branch was stripped. This code filters them out. Note that the
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
199 # branch that ceased to exist may not be in newbranches because
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
200 # newbranches is the set of candidate heads, which when you strip the
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
201 # last commit in a branch will be the parent branch.
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
202 droppednodes = []
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
203 for branch in self.keys():
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
204 nodes = [head for head in self[branch]
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
205 if cl.hasnode(head)]
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
206 if not nodes:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
207 droppednodes.extend(nodes)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
208 del self[branch]
18132
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
209 if ((not self.validfor(repo)) or (self.tipnode in droppednodes)):
db25bf1dc828 branchmap: move validity logic in the object itself
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18131
diff changeset
210
18131
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
211 # cache key are not valid anymore
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
212 self.tipnode = nullid
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
213 self.tiprev = nullrev
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
214 for heads in self.values():
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
215 tiprev = max(cl.rev(node) for node in heads)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
216 if tiprev > self.tiprev:
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
217 self.tipnode = cl.node(tiprev)
f0eeb9b3444a branchmap: make update a method
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18130
diff changeset
218 self.tiprev = tiprev
18168
c351759ab0a0 branchmap: takes filtered revision in account for cache calculation
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18167
diff changeset
219 self.filteredhash = self._hashfiltered(repo)