159 # heads. |
159 # heads. |
160 if closednodes is None: |
160 if closednodes is None: |
161 self._closednodes = set() |
161 self._closednodes = set() |
162 else: |
162 else: |
163 self._closednodes = closednodes |
163 self._closednodes = closednodes |
164 self.entries = dict(entries) |
164 self._entries = dict(entries) |
165 |
165 |
166 def __iter__(self): |
166 def __iter__(self): |
167 return iter(self.entries) |
167 return iter(self._entries) |
168 |
168 |
169 def __setitem__(self, key, value): |
169 def __setitem__(self, key, value): |
170 self.entries[key] = value |
170 self._entries[key] = value |
171 |
171 |
172 def __getitem__(self, key): |
172 def __getitem__(self, key): |
173 return self.entries[key] |
173 return self._entries[key] |
174 |
174 |
175 def iteritems(self): |
175 def iteritems(self): |
176 return self.entries.iteritems() |
176 return self._entries.iteritems() |
177 |
177 |
178 def hasbranch(self, label): |
178 def hasbranch(self, label): |
179 """ checks whether a branch of this name exists or not """ |
179 """ checks whether a branch of this name exists or not """ |
180 return label in self.entries |
180 return label in self._entries |
181 |
181 |
182 @classmethod |
182 @classmethod |
183 def fromfile(cls, repo): |
183 def fromfile(cls, repo): |
184 f = None |
184 f = None |
185 try: |
185 try: |
228 label = encoding.tolocal(label.strip()) |
228 label = encoding.tolocal(label.strip()) |
229 node = bin(node) |
229 node = bin(node) |
230 if not cl.hasnode(node): |
230 if not cl.hasnode(node): |
231 raise ValueError( |
231 raise ValueError( |
232 r'node %s does not exist' % pycompat.sysstr(hex(node))) |
232 r'node %s does not exist' % pycompat.sysstr(hex(node))) |
233 self.entries.setdefault(label, []).append(node) |
233 self._entries.setdefault(label, []).append(node) |
234 if state == 'c': |
234 if state == 'c': |
235 self._closednodes.add(node) |
235 self._closednodes.add(node) |
236 |
236 |
237 @staticmethod |
237 @staticmethod |
238 def _filename(repo): |
238 def _filename(repo): |
285 for bn, heads in self.iteritems(): |
285 for bn, heads in self.iteritems(): |
286 yield (bn, heads) + self._branchtip(heads) |
286 yield (bn, heads) + self._branchtip(heads) |
287 |
287 |
288 def iterheads(self): |
288 def iterheads(self): |
289 """ returns all the heads """ |
289 """ returns all the heads """ |
290 return self.entries.itervalues() |
290 return self._entries.itervalues() |
291 |
291 |
292 def copy(self): |
292 def copy(self): |
293 """return an deep copy of the branchcache object""" |
293 """return an deep copy of the branchcache object""" |
294 return branchcache( |
294 return branchcache( |
295 self.entries, self.tipnode, self.tiprev, self.filteredhash, |
295 self._entries, self.tipnode, self.tiprev, self.filteredhash, |
296 self._closednodes) |
296 self._closednodes) |
297 |
297 |
298 def write(self, repo): |
298 def write(self, repo): |
299 try: |
299 try: |
300 f = repo.cachevfs(self._filename(repo), "w", atomictemp=True) |
300 f = repo.cachevfs(self._filename(repo), "w", atomictemp=True) |
313 state = 'o' |
313 state = 'o' |
314 f.write("%s %s %s\n" % (hex(node), state, label)) |
314 f.write("%s %s %s\n" % (hex(node), state, label)) |
315 f.close() |
315 f.close() |
316 repo.ui.log('branchcache', |
316 repo.ui.log('branchcache', |
317 'wrote %s branch cache with %d labels and %d nodes\n', |
317 'wrote %s branch cache with %d labels and %d nodes\n', |
318 repo.filtername, len(self.entries), nodecount) |
318 repo.filtername, len(self._entries), nodecount) |
319 except (IOError, OSError, error.Abort) as inst: |
319 except (IOError, OSError, error.Abort) as inst: |
320 # Abort may be raised by read only opener, so log and continue |
320 # Abort may be raised by read only opener, so log and continue |
321 repo.ui.debug("couldn't write branch cache: %s\n" % |
321 repo.ui.debug("couldn't write branch cache: %s\n" % |
322 stringutil.forcebytestr(inst)) |
322 stringutil.forcebytestr(inst)) |
323 |
323 |
342 |
342 |
343 # if older branchheads are reachable from new ones, they aren't |
343 # if older branchheads are reachable from new ones, they aren't |
344 # really branchheads. Note checking parents is insufficient: |
344 # really branchheads. Note checking parents is insufficient: |
345 # 1 (branch a) -> 2 (branch b) -> 3 (branch a) |
345 # 1 (branch a) -> 2 (branch b) -> 3 (branch a) |
346 for branch, newheadrevs in newbranches.iteritems(): |
346 for branch, newheadrevs in newbranches.iteritems(): |
347 bheads = self.entries.setdefault(branch, []) |
347 bheads = self._entries.setdefault(branch, []) |
348 bheadset = set(cl.rev(node) for node in bheads) |
348 bheadset = set(cl.rev(node) for node in bheads) |
349 |
349 |
350 # This have been tested True on all internal usage of this function. |
350 # This have been tested True on all internal usage of this function. |
351 # run it again in case of doubt |
351 # run it again in case of doubt |
352 # assert not (set(bheadrevs) & set(newheadrevs)) |
352 # assert not (set(bheadrevs) & set(newheadrevs)) |