125 |
125 |
126 def clear(self): |
126 def clear(self): |
127 self._per_filter.clear() |
127 self._per_filter.clear() |
128 |
128 |
129 |
129 |
130 class branchcache(dict): |
130 class branchcache(object): |
131 """A dict like object that hold branches heads cache. |
131 """A dict like object that hold branches heads cache. |
132 |
132 |
133 This cache is used to avoid costly computations to determine all the |
133 This cache is used to avoid costly computations to determine all the |
134 branch heads of a repo. |
134 branch heads of a repo. |
135 |
135 |
149 branch head closes a branch or not. |
149 branch head closes a branch or not. |
150 """ |
150 """ |
151 |
151 |
152 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev, |
152 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev, |
153 filteredhash=None, closednodes=None): |
153 filteredhash=None, closednodes=None): |
154 super(branchcache, self).__init__(entries) |
|
155 self.tipnode = tipnode |
154 self.tipnode = tipnode |
156 self.tiprev = tiprev |
155 self.tiprev = tiprev |
157 self.filteredhash = filteredhash |
156 self.filteredhash = filteredhash |
158 # closednodes is a set of nodes that close their branch. If the branch |
157 # closednodes is a set of nodes that close their branch. If the branch |
159 # cache has been updated, it may contain nodes that are no longer |
158 # cache has been updated, it may contain nodes that are no longer |
160 # heads. |
159 # heads. |
161 if closednodes is None: |
160 if closednodes is None: |
162 self._closednodes = set() |
161 self._closednodes = set() |
163 else: |
162 else: |
164 self._closednodes = closednodes |
163 self._closednodes = closednodes |
|
164 self.entries = dict(entries) |
|
165 |
|
166 def __iter__(self): |
|
167 return iter(self.entries) |
|
168 |
|
169 def __setitem__(self, key, value): |
|
170 self.entries[key] = value |
|
171 |
|
172 def __getitem__(self, key): |
|
173 return self.entries[key] |
|
174 |
|
175 def setdefault(self, *args): |
|
176 return self.entries.setdefault(*args) |
|
177 |
|
178 def iteritems(self): |
|
179 return self.entries.iteritems() |
|
180 |
|
181 def itervalues(self): |
|
182 return self.entries.itervalues() |
165 |
183 |
166 @classmethod |
184 @classmethod |
167 def fromfile(cls, repo): |
185 def fromfile(cls, repo): |
168 f = None |
186 f = None |
169 try: |
187 try: |
269 for bn, heads in self.iteritems(): |
287 for bn, heads in self.iteritems(): |
270 yield (bn, heads) + self._branchtip(heads) |
288 yield (bn, heads) + self._branchtip(heads) |
271 |
289 |
272 def copy(self): |
290 def copy(self): |
273 """return an deep copy of the branchcache object""" |
291 """return an deep copy of the branchcache object""" |
274 return type(self)( |
292 return branchcache( |
275 self, self.tipnode, self.tiprev, self.filteredhash, |
293 self.entries, self.tipnode, self.tiprev, self.filteredhash, |
276 self._closednodes) |
294 self._closednodes) |
277 |
295 |
278 def write(self, repo): |
296 def write(self, repo): |
279 try: |
297 try: |
280 f = repo.cachevfs(self._filename(repo), "w", atomictemp=True) |
298 f = repo.cachevfs(self._filename(repo), "w", atomictemp=True) |
293 state = 'o' |
311 state = 'o' |
294 f.write("%s %s %s\n" % (hex(node), state, label)) |
312 f.write("%s %s %s\n" % (hex(node), state, label)) |
295 f.close() |
313 f.close() |
296 repo.ui.log('branchcache', |
314 repo.ui.log('branchcache', |
297 'wrote %s branch cache with %d labels and %d nodes\n', |
315 'wrote %s branch cache with %d labels and %d nodes\n', |
298 repo.filtername, len(self), nodecount) |
316 repo.filtername, len(self.entries), nodecount) |
299 except (IOError, OSError, error.Abort) as inst: |
317 except (IOError, OSError, error.Abort) as inst: |
300 # Abort may be raised by read only opener, so log and continue |
318 # Abort may be raised by read only opener, so log and continue |
301 repo.ui.debug("couldn't write branch cache: %s\n" % |
319 repo.ui.debug("couldn't write branch cache: %s\n" % |
302 stringutil.forcebytestr(inst)) |
320 stringutil.forcebytestr(inst)) |
303 |
321 |
349 |
367 |
350 if not self.validfor(repo): |
368 if not self.validfor(repo): |
351 # cache key are not valid anymore |
369 # cache key are not valid anymore |
352 self.tipnode = nullid |
370 self.tipnode = nullid |
353 self.tiprev = nullrev |
371 self.tiprev = nullrev |
354 for heads in self.values(): |
372 for heads in self.itervalues(): |
355 tiprev = max(cl.rev(node) for node in heads) |
373 tiprev = max(cl.rev(node) for node in heads) |
356 if tiprev > self.tiprev: |
374 if tiprev > self.tiprev: |
357 self.tipnode = cl.node(tiprev) |
375 self.tipnode = cl.node(tiprev) |
358 self.tiprev = tiprev |
376 self.tiprev = tiprev |
359 self.filteredhash = scmutil.filteredhash(repo, self.tiprev) |
377 self.filteredhash = scmutil.filteredhash(repo, self.tiprev) |