branchcache: store filtered hash and obsolete hash independently for V3
This will avoid the bug covered in tests/test-branches-obsolete.t when we stop
storing all heads explicitly in V3.
--- a/mercurial/branchmap.py Wed Mar 06 12:07:31 2024 +0100
+++ b/mercurial/branchmap.py Wed Mar 06 11:39:44 2024 +0100
@@ -813,14 +813,16 @@
- tip-rev: the rev-num of the tip-most revision seen by this cache
- tip-node: the node-id of the tip-most revision sen by this cache
- - filtered-hash: the hash of all filtered and obsolete revisions (before
+ - filtered-hash: the hash of all filtered revisions (before tip-rev)
+ ignored by this cache.
+ - obsolete-hash: the hash of all non-filtered obsolete revisions (before
tip-rev) ignored by this cache.
The tip-rev is used to know how far behind the value in the file are
compared to the current repository state.
- The tip-node and filtered-hash are used to detect if this cache can be used
- for this repository state at all.
+ The tip-node, filtered-hash and obsolete-hash are used to detect if this
+ cache can be used for this repository state at all.
The open/closed state is represented by a single letter 'o' or 'c'.
This field can be used to avoid changelog reads when determining if a
@@ -828,6 +830,7 @@
"""
_base_filename = b"branch3"
+ _default_key_hashes = (None, None)
def _write_header(self, fp) -> None:
cache_keys = {
@@ -835,7 +838,10 @@
b"tip-rev": b'%d' % self.tiprev,
}
if self.key_hashes:
- cache_keys[b"filtered-hash"] = hex(self.key_hashes[0])
+ if self.key_hashes[0] is not None:
+ cache_keys[b"filtered-hash"] = hex(self.key_hashes[0])
+ if self.key_hashes[1] is not None:
+ cache_keys[b"obsolete-hash"] = hex(self.key_hashes[1])
pieces = (b"%s=%s" % i for i in sorted(cache_keys.items()))
fp.write(b" ".join(pieces) + b'\n')
@@ -846,29 +852,29 @@
cache_keys = dict(p.split(b'=', 1) for p in pieces)
args = {}
+ filtered_hash = None
+ obsolete_hash = None
for k, v in cache_keys.items():
if k == b"tip-rev":
args["tiprev"] = int(v)
elif k == b"tip-node":
args["tipnode"] = bin(v)
elif k == b"filtered-hash":
- args["key_hashes"] = (bin(v),)
+ filtered_hash = bin(v)
+ elif k == b"obsolete-hash":
+ obsolete_hash = bin(v)
else:
msg = b"unknown cache key: %r" % k
raise ValueError(msg)
+ args["key_hashes"] = (filtered_hash, obsolete_hash)
return args
def _compute_key_hashes(self, repo) -> Tuple[bytes]:
"""return the cache key hashes that match this repoview state"""
- filtered_hash = scmutil.combined_filtered_and_obsolete_hash(
+ return scmutil.filtered_and_obsolete_hash(
repo,
self.tiprev,
- needobsolete=True,
)
- if filtered_hash is None:
- return cast(Tuple[bytes], ())
- else:
- return (filtered_hash,)
class remotebranchcache(_BaseBranchCache):
--- a/mercurial/scmutil.py Wed Mar 06 12:07:31 2024 +0100
+++ b/mercurial/scmutil.py Wed Mar 06 11:39:44 2024 +0100
@@ -385,6 +385,37 @@
return result
+def filtered_and_obsolete_hash(repo, maxrev):
+ """build hashs of filtered and obsolete revisions in the current repoview.
+
+ Multiple caches perform up-to-date validation by checking that the
+ tiprev and tipnode stored in the cache file match the current repository.
+ However, this is not sufficient for validating repoviews because the set
+ of revisions in the view may change without the repository tiprev and
+ tipnode changing.
+
+ This function hashes all the revs filtered from the view up to maxrev and
+ returns that SHA-1 digest. The obsolete revisions hashed are only the
+ non-filtered one.
+ """
+ cl = repo.changelog
+ obs_set = obsolete.getrevs(repo, b'obsolete')
+ key = (maxrev, hash(cl.filteredrevs), hash(obs_set))
+
+ result = cl._filteredrevs_hashcache.get(key)
+ if result is None:
+ filtered_hash = None
+ obs_hash = None
+ filtered_revs, obs_revs = _filtered_and_obs_revs(repo, maxrev)
+ if filtered_revs:
+ filtered_hash = _hash_revs(filtered_revs)
+ if obs_revs:
+ obs_hash = _hash_revs(obs_revs)
+ result = (filtered_hash, obs_hash)
+ cl._filteredrevs_hashcache[key] = result
+ return result
+
+
def _filtered_and_obs_revs(repo, max_rev):
"""return the set of filtered and non-filtered obsolete revision"""
cl = repo.changelog
--- a/tests/test-branches-obsolete.t Wed Mar 06 12:07:31 2024 +0100
+++ b/tests/test-branches-obsolete.t Wed Mar 06 11:39:44 2024 +0100
@@ -210,11 +210,11 @@
#else
$ show_cache
##### .hg/cache/branch3
- filtered-hash=a943c3355ad9e93654d58b1c934c7c4329a5d1d4 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
+ obsolete-hash=b6d2b1f5b70f09c25c835edcae69be35f681605c tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
550bb31f072912453ccbb503de1d554616911e88 o default
7c29ff2453bf38c75ee8982935739103c38a9284 o default
##### .hg/cache/branch3-served
- filtered-hash=a943c3355ad9e93654d58b1c934c7c4329a5d1d4 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
+ filtered-hash=f8006d64a10d35c011a5c5fa88be1e25c5929514 obsolete-hash=ac5282439f301518f362f37547fcd52bcc670373 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
550bb31f072912453ccbb503de1d554616911e88 o default
7c29ff2453bf38c75ee8982935739103c38a9284 o default
#endif
@@ -235,7 +235,7 @@
#else
$ show_cache
##### .hg/cache/branch3-served
- filtered-hash=a943c3355ad9e93654d58b1c934c7c4329a5d1d4 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
+ filtered-hash=f8006d64a10d35c011a5c5fa88be1e25c5929514 obsolete-hash=ac5282439f301518f362f37547fcd52bcc670373 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
550bb31f072912453ccbb503de1d554616911e88 o default
7c29ff2453bf38c75ee8982935739103c38a9284 o default
#endif
@@ -304,11 +304,11 @@
#else
$ show_cache
##### .hg/cache/branch3
- filtered-hash=a943c3355ad9e93654d58b1c934c7c4329a5d1d4 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
+ obsolete-hash=b6d2b1f5b70f09c25c835edcae69be35f681605c tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
550bb31f072912453ccbb503de1d554616911e88 o default
7c29ff2453bf38c75ee8982935739103c38a9284 o default
##### .hg/cache/branch3-served
- filtered-hash=f8006d64a10d35c011a5c5fa88be1e25c5929514 tip-node=7c29ff2453bf38c75ee8982935739103c38a9284 tip-rev=7
+ filtered-hash=f1456c0d675980582dda9b8edc7f13f503ce544f obsolete-hash=3e74f5349008671629e39d13d7e00d9ba94c74f7 tip-node=7c29ff2453bf38c75ee8982935739103c38a9284 tip-rev=7
550bb31f072912453ccbb503de1d554616911e88 o default
7c29ff2453bf38c75ee8982935739103c38a9284 o default
#endif
@@ -329,7 +329,7 @@
#else
$ show_cache
##### .hg/cache/branch3-served
- filtered-hash=f8006d64a10d35c011a5c5fa88be1e25c5929514 tip-node=7c29ff2453bf38c75ee8982935739103c38a9284 tip-rev=7
+ filtered-hash=f1456c0d675980582dda9b8edc7f13f503ce544f obsolete-hash=3e74f5349008671629e39d13d7e00d9ba94c74f7 tip-node=7c29ff2453bf38c75ee8982935739103c38a9284 tip-rev=7
550bb31f072912453ccbb503de1d554616911e88 o default
7c29ff2453bf38c75ee8982935739103c38a9284 o default
#endif
@@ -405,7 +405,7 @@
#else
$ show_cache
##### .hg/cache/branch3-served
- filtered-hash=ac5282439f301518f362f37547fcd52bcc670373 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
+ obsolete-hash=ac5282439f301518f362f37547fcd52bcc670373 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
63ba7cd843d1e95aac1a24435befeb1909c53619 o default
7c29ff2453bf38c75ee8982935739103c38a9284 o default
#endif
@@ -426,7 +426,7 @@
#else
$ show_cache
##### .hg/cache/branch3-served
- filtered-hash=ac5282439f301518f362f37547fcd52bcc670373 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
+ obsolete-hash=ac5282439f301518f362f37547fcd52bcc670373 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
63ba7cd843d1e95aac1a24435befeb1909c53619 o default
7c29ff2453bf38c75ee8982935739103c38a9284 o default
#endif
@@ -516,7 +516,7 @@
#else
$ show_cache
##### .hg/cache/branch3-served
- filtered-hash=f8006d64a10d35c011a5c5fa88be1e25c5929514 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
+ filtered-hash=f1456c0d675980582dda9b8edc7f13f503ce544f obsolete-hash=3e74f5349008671629e39d13d7e00d9ba94c74f7 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
550bb31f072912453ccbb503de1d554616911e88 o default
3d808bbc94408ea19da905596d4079357a1f28be o default
#endif
@@ -537,7 +537,7 @@
#else
$ show_cache
##### .hg/cache/branch3-served
- filtered-hash=f8006d64a10d35c011a5c5fa88be1e25c5929514 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
+ filtered-hash=f1456c0d675980582dda9b8edc7f13f503ce544f obsolete-hash=3e74f5349008671629e39d13d7e00d9ba94c74f7 tip-node=3d808bbc94408ea19da905596d4079357a1f28be tip-rev=8
550bb31f072912453ccbb503de1d554616911e88 o default
3d808bbc94408ea19da905596d4079357a1f28be o default
#endif