Mercurial > public > mercurial-scm > hg-stable
diff mercurial/branchmap.py @ 51515: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 |
line wrap: on
line diff
--- a/mercurial/branchmap.py Fri Jan 19 11:30:10 2024 +0100 +++ b/mercurial/branchmap.py Mon Feb 19 11:43:19 2024 +0100 @@ -60,6 +60,10 @@ def __getitem__(self, repo): self.updatecache(repo) bcache = self._per_filter[repo.filtername] + assert bcache._repo.filtername == repo.filtername, ( + bcache._repo.filtername, + repo.filtername, + ) return bcache def update_disk(self, repo): @@ -76,6 +80,10 @@ """ self.updatecache(repo) bcache = self._per_filter[repo.filtername] + assert bcache._repo.filtername == repo.filtername, ( + bcache._repo.filtername, + repo.filtername, + ) bcache.write(repo) def updatecache(self, repo): @@ -99,7 +107,7 @@ subsetname = subsettable.get(filtername) if subsetname is not None: subset = repo.filtered(subsetname) - bcache = self[subset].copy() + bcache = self[subset].copy(repo) extrarevs = subset.changelog.filteredrevs - cl.filteredrevs revs.extend(r for r in extrarevs if r <= bcache.tiprev) else: @@ -148,7 +156,7 @@ for candidate in (b'base', b'immutable', b'served'): rview = repo.filtered(candidate) if cache.validfor(rview): - self._per_filter[candidate] = cache + cache = self._per_filter[candidate] = cache.copy(rview) cache.write(rview) return @@ -415,10 +423,10 @@ self._verifyall() return self._entries.values() - def copy(self): + def copy(self, repo): """return an deep copy of the branchcache object""" return type(self)( - self._repo, + repo, self._entries, self.tipnode, self.tiprev, @@ -427,6 +435,10 @@ ) def write(self, repo): + assert self._repo.filtername == repo.filtername, ( + self._repo.filtername, + repo.filtername, + ) tr = repo.currenttransaction() if not getattr(tr, 'finalized', True): # Avoid premature writing. @@ -471,6 +483,10 @@ missing heads, and a generator of nodes that are strictly a superset of heads missing, this function updates self to be correct. """ + assert self._repo.filtername == repo.filtername, ( + self._repo.filtername, + repo.filtername, + ) starttime = util.timer() cl = repo.changelog # collect new branch entries