comparison mercurial/branchmap.py @ 18132:db25bf1dc828

branchmap: move validity logic in the object itself In several place, We check if a branchcache is still valid regarding the current state of the repository. This changeset puts this logic in a method of the object that can be reused when necessary. A branch map is considered valid whenever it is up to date or a strict subset of the repository state. The change will help making branchcache aware of filtered revision. The change in keyword is expected. the branch cache is actually invalid after the amend. The previous check did not detected it.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Mon, 24 Dec 2012 02:49:59 +0100
parents f0eeb9b3444a
children 3a2e810dd3d8
comparison
equal deleted inserted replaced
18131:f0eeb9b3444a 18132:db25bf1dc828
7 7
8 from node import bin, hex, nullid, nullrev 8 from node import bin, hex, nullid, nullrev
9 import encoding 9 import encoding
10 10
11 def read(repo): 11 def read(repo):
12 partial = branchcache()
13 try: 12 try:
14 f = repo.opener("cache/branchheads") 13 f = repo.opener("cache/branchheads")
15 lines = f.read().split('\n') 14 lines = f.read().split('\n')
16 f.close() 15 f.close()
17 except (IOError, OSError): 16 except (IOError, OSError):
18 return branchcache() 17 return branchcache()
19 18
20 try: 19 try:
21 last, lrev = lines.pop(0).split(" ", 1) 20 last, lrev = lines.pop(0).split(" ", 1)
22 last, lrev = bin(last), int(lrev) 21 last, lrev = bin(last), int(lrev)
23 if lrev >= len(repo) or repo[lrev].node() != last: 22 partial = branchcache(tipnode=last, tiprev=lrev)
23 if not partial.validfor(repo):
24 # invalidate the cache 24 # invalidate the cache
25 raise ValueError('invalidating branch cache (tip differs)') 25 raise ValueError('invalidating branch cache (tip differs)')
26 for l in lines: 26 for l in lines:
27 if not l: 27 if not l:
28 continue 28 continue
30 label = encoding.tolocal(label.strip()) 30 label = encoding.tolocal(label.strip())
31 if not node in repo: 31 if not node in repo:
32 raise ValueError('invalidating branch cache because node '+ 32 raise ValueError('invalidating branch cache because node '+
33 '%s does not exist' % node) 33 '%s does not exist' % node)
34 partial.setdefault(label, []).append(bin(node)) 34 partial.setdefault(label, []).append(bin(node))
35 partial.tipnode = last
36 partial.tiprev = lrev
37 except KeyboardInterrupt: 35 except KeyboardInterrupt:
38 raise 36 raise
39 except Exception, inst: 37 except Exception, inst:
40 if repo.ui.debugflag: 38 if repo.ui.debugflag:
41 repo.ui.warn(str(inst), '\n') 39 repo.ui.warn(str(inst), '\n')
45 43
46 44
47 def updatecache(repo): 45 def updatecache(repo):
48 repo = repo.unfiltered() # Until we get a smarter cache management 46 repo = repo.unfiltered() # Until we get a smarter cache management
49 cl = repo.changelog 47 cl = repo.changelog
50 tip = cl.tip()
51 partial = repo._branchcache 48 partial = repo._branchcache
52 if partial is not None and partial.tipnode == tip:
53 return
54 49
55 if partial is None or partial.tipnode not in cl.nodemap: 50 if partial is None or not partial.validfor(repo):
56 partial = read(repo) 51 partial = read(repo)
57 52
58 catip = repo._cacheabletip() 53 catip = repo._cacheabletip()
59 # if partial.tiprev == catip: cache is already up to date 54 # if partial.tiprev == catip: cache is already up to date
60 # if partial.tiprev > catip: we have uncachable element in `partial` can't 55 # if partial.tiprev > catip: we have uncachable element in `partial` can't
77 72
78 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev): 73 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev):
79 super(branchcache, self).__init__(entries) 74 super(branchcache, self).__init__(entries)
80 self.tipnode = tipnode 75 self.tipnode = tipnode
81 self.tiprev = tiprev 76 self.tiprev = tiprev
77
78 def validfor(self, repo):
79 """Is the cache content valide regarding a repo
80
81 - False when cached tipnode are unknown or if we detect a strip.
82 - True when cache is up to date or a subset of current repo."""
83 try:
84 return self.tipnode == repo.changelog.node(self.tiprev)
85 except IndexError:
86 return False
87
82 88
83 def write(self, repo): 89 def write(self, repo):
84 try: 90 try:
85 f = repo.opener("cache/branchheads", "w", atomictemp=True) 91 f = repo.opener("cache/branchheads", "w", atomictemp=True)
86 f.write("%s %s\n" % (hex(self.tipnode), self.tiprev)) 92 f.write("%s %s\n" % (hex(self.tipnode), self.tiprev))
155 nodes = [head for head in self[branch] 161 nodes = [head for head in self[branch]
156 if cl.hasnode(head)] 162 if cl.hasnode(head)]
157 if not nodes: 163 if not nodes:
158 droppednodes.extend(nodes) 164 droppednodes.extend(nodes)
159 del self[branch] 165 del self[branch]
160 try: 166 if ((not self.validfor(repo)) or (self.tipnode in droppednodes)):
161 node = cl.node(self.tiprev) 167
162 except IndexError:
163 node = None
164 if ((self.tipnode != node)
165 or (self.tipnode in droppednodes)):
166 # cache key are not valid anymore 168 # cache key are not valid anymore
167 self.tipnode = nullid 169 self.tipnode = nullid
168 self.tiprev = nullrev 170 self.tiprev = nullrev
169 for heads in self.values(): 171 for heads in self.values():
170 tiprev = max(cl.rev(node) for node in heads) 172 tiprev = max(cl.rev(node) for node in heads)