5 # This software may be used and distributed according to the terms of the |
5 # This software may be used and distributed according to the terms of the |
6 # GNU General Public License version 2 or any later version. |
6 # GNU General Public License version 2 or any later version. |
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 import scmutil |
10 import util |
11 import util |
11 import time |
12 import time |
12 from array import array |
13 from array import array |
13 from struct import calcsize, pack, unpack |
14 from struct import calcsize, pack, unpack |
14 |
15 |
134 if closednodes is None: |
135 if closednodes is None: |
135 self._closednodes = set() |
136 self._closednodes = set() |
136 else: |
137 else: |
137 self._closednodes = closednodes |
138 self._closednodes = closednodes |
138 |
139 |
139 def _hashfiltered(self, repo): |
|
140 """build hash of revision filtered in the current cache |
|
141 |
|
142 Tracking tipnode and tiprev is not enough to ensure validity of the |
|
143 cache as they do not help to distinct cache that ignored various |
|
144 revision bellow tiprev. |
|
145 |
|
146 To detect such difference, we build a cache of all ignored revisions. |
|
147 """ |
|
148 cl = repo.changelog |
|
149 if not cl.filteredrevs: |
|
150 return None |
|
151 key = None |
|
152 revs = sorted(r for r in cl.filteredrevs if r <= self.tiprev) |
|
153 if revs: |
|
154 s = util.sha1() |
|
155 for rev in revs: |
|
156 s.update('%s;' % rev) |
|
157 key = s.digest() |
|
158 return key |
|
159 |
|
160 def validfor(self, repo): |
140 def validfor(self, repo): |
161 """Is the cache content valid regarding a repo |
141 """Is the cache content valid regarding a repo |
162 |
142 |
163 - False when cached tipnode is unknown or if we detect a strip. |
143 - False when cached tipnode is unknown or if we detect a strip. |
164 - True when cache is up to date or a subset of current repo.""" |
144 - True when cache is up to date or a subset of current repo.""" |
165 try: |
145 try: |
166 return ((self.tipnode == repo.changelog.node(self.tiprev)) |
146 return ((self.tipnode == repo.changelog.node(self.tiprev)) |
167 and (self.filteredhash == self._hashfiltered(repo))) |
147 and (self.filteredhash == \ |
|
148 scmutil.filteredhash(repo, self.tiprev))) |
168 except IndexError: |
149 except IndexError: |
169 return False |
150 return False |
170 |
151 |
171 def _branchtip(self, heads): |
152 def _branchtip(self, heads): |
172 '''Return tuple with last open head in heads and false, |
153 '''Return tuple with last open head in heads and false, |
281 for heads in self.values(): |
262 for heads in self.values(): |
282 tiprev = max(cl.rev(node) for node in heads) |
263 tiprev = max(cl.rev(node) for node in heads) |
283 if tiprev > self.tiprev: |
264 if tiprev > self.tiprev: |
284 self.tipnode = cl.node(tiprev) |
265 self.tipnode = cl.node(tiprev) |
285 self.tiprev = tiprev |
266 self.tiprev = tiprev |
286 self.filteredhash = self._hashfiltered(repo) |
267 self.filteredhash = scmutil.filteredhash(repo, self.tiprev) |
287 |
268 |
288 duration = time.time() - starttime |
269 duration = time.time() - starttime |
289 repo.ui.log('branchcache', 'updated %s branch cache in %.4f seconds\n', |
270 repo.ui.log('branchcache', 'updated %s branch cache in %.4f seconds\n', |
290 repo.filtername, duration) |
271 repo.filtername, duration) |
291 |
272 |