Mercurial > public > mercurial-scm > hg
comparison mercurial/branchmap.py @ 51447:3aba79ce52a9
branchcache: pass the target repository when copying
Branchmap are usually copied to be used on a different repoview using a
different filter level. Passing the repository around means the repository in
`branchcache._repo` will drift from the actual branchmap filter.
This is currently "fine" because the repo is only used to retrieve the `nullid`
value. However, this is a fairly big trap for any extension or future code using
the `_repo` attribute.
The replace logic is now using a copy to ensure the right repository view is
used to initialized the cached value.
We add a couple of assert for make sure this inconsistency does not sneak back.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 19 Feb 2024 11:43:19 +0100 |
parents | 7f7086a42b2b |
children | fd30c4301929 |
comparison
equal
deleted
inserted
replaced
51446:7f7086a42b2b | 51447:3aba79ce52a9 |
---|---|
58 self._per_filter = {} | 58 self._per_filter = {} |
59 | 59 |
60 def __getitem__(self, repo): | 60 def __getitem__(self, repo): |
61 self.updatecache(repo) | 61 self.updatecache(repo) |
62 bcache = self._per_filter[repo.filtername] | 62 bcache = self._per_filter[repo.filtername] |
63 assert bcache._repo.filtername == repo.filtername, ( | |
64 bcache._repo.filtername, | |
65 repo.filtername, | |
66 ) | |
63 return bcache | 67 return bcache |
64 | 68 |
65 def update_disk(self, repo): | 69 def update_disk(self, repo): |
66 """ensure and up-to-date cache is (or will be) written on disk | 70 """ensure and up-to-date cache is (or will be) written on disk |
67 | 71 |
74 This method exist independently of __getitem__ as it is sometime useful | 78 This method exist independently of __getitem__ as it is sometime useful |
75 to signal that we have no intend to use the data in memory yet. | 79 to signal that we have no intend to use the data in memory yet. |
76 """ | 80 """ |
77 self.updatecache(repo) | 81 self.updatecache(repo) |
78 bcache = self._per_filter[repo.filtername] | 82 bcache = self._per_filter[repo.filtername] |
83 assert bcache._repo.filtername == repo.filtername, ( | |
84 bcache._repo.filtername, | |
85 repo.filtername, | |
86 ) | |
79 bcache.write(repo) | 87 bcache.write(repo) |
80 | 88 |
81 def updatecache(self, repo): | 89 def updatecache(self, repo): |
82 """Update the cache for the given filtered view on a repository""" | 90 """Update the cache for the given filtered view on a repository""" |
83 # This can trigger updates for the caches for subsets of the filtered | 91 # This can trigger updates for the caches for subsets of the filtered |
97 # the cache for a subset, then extend that to add info on missing | 105 # the cache for a subset, then extend that to add info on missing |
98 # revisions. | 106 # revisions. |
99 subsetname = subsettable.get(filtername) | 107 subsetname = subsettable.get(filtername) |
100 if subsetname is not None: | 108 if subsetname is not None: |
101 subset = repo.filtered(subsetname) | 109 subset = repo.filtered(subsetname) |
102 bcache = self[subset].copy() | 110 bcache = self[subset].copy(repo) |
103 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs | 111 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs |
104 revs.extend(r for r in extrarevs if r <= bcache.tiprev) | 112 revs.extend(r for r in extrarevs if r <= bcache.tiprev) |
105 else: | 113 else: |
106 # nothing to fall back on, start empty. | 114 # nothing to fall back on, start empty. |
107 bcache = branchcache(repo) | 115 bcache = branchcache(repo) |
146 # Try to stick it as low as possible | 154 # Try to stick it as low as possible |
147 # filter above served are unlikely to be fetch from a clone | 155 # filter above served are unlikely to be fetch from a clone |
148 for candidate in (b'base', b'immutable', b'served'): | 156 for candidate in (b'base', b'immutable', b'served'): |
149 rview = repo.filtered(candidate) | 157 rview = repo.filtered(candidate) |
150 if cache.validfor(rview): | 158 if cache.validfor(rview): |
151 self._per_filter[candidate] = cache | 159 cache = self._per_filter[candidate] = cache.copy(rview) |
152 cache.write(rview) | 160 cache.write(rview) |
153 return | 161 return |
154 | 162 |
155 def clear(self): | 163 def clear(self): |
156 self._per_filter.clear() | 164 self._per_filter.clear() |
413 def iterheads(self): | 421 def iterheads(self): |
414 """returns all the heads""" | 422 """returns all the heads""" |
415 self._verifyall() | 423 self._verifyall() |
416 return self._entries.values() | 424 return self._entries.values() |
417 | 425 |
418 def copy(self): | 426 def copy(self, repo): |
419 """return an deep copy of the branchcache object""" | 427 """return an deep copy of the branchcache object""" |
420 return type(self)( | 428 return type(self)( |
421 self._repo, | 429 repo, |
422 self._entries, | 430 self._entries, |
423 self.tipnode, | 431 self.tipnode, |
424 self.tiprev, | 432 self.tiprev, |
425 self.filteredhash, | 433 self.filteredhash, |
426 self._closednodes, | 434 self._closednodes, |
427 ) | 435 ) |
428 | 436 |
429 def write(self, repo): | 437 def write(self, repo): |
438 assert self._repo.filtername == repo.filtername, ( | |
439 self._repo.filtername, | |
440 repo.filtername, | |
441 ) | |
430 tr = repo.currenttransaction() | 442 tr = repo.currenttransaction() |
431 if not getattr(tr, 'finalized', True): | 443 if not getattr(tr, 'finalized', True): |
432 # Avoid premature writing. | 444 # Avoid premature writing. |
433 # | 445 # |
434 # (The cache warming setup by localrepo will update the file later.) | 446 # (The cache warming setup by localrepo will update the file later.) |
469 def update(self, repo, revgen): | 481 def update(self, repo, revgen): |
470 """Given a branchhead cache, self, that may have extra nodes or be | 482 """Given a branchhead cache, self, that may have extra nodes or be |
471 missing heads, and a generator of nodes that are strictly a superset of | 483 missing heads, and a generator of nodes that are strictly a superset of |
472 heads missing, this function updates self to be correct. | 484 heads missing, this function updates self to be correct. |
473 """ | 485 """ |
486 assert self._repo.filtername == repo.filtername, ( | |
487 self._repo.filtername, | |
488 repo.filtername, | |
489 ) | |
474 starttime = util.timer() | 490 starttime = util.timer() |
475 cl = repo.changelog | 491 cl = repo.changelog |
476 # collect new branch entries | 492 # collect new branch entries |
477 newbranches = {} | 493 newbranches = {} |
478 getbranchinfo = repo.revbranchcache().branchinfo | 494 getbranchinfo = repo.revbranchcache().branchinfo |