# HG changeset patch # User Anton Shestakov # Date 1630237283 -10800 # Node ID 6c67219ce7791e210c967ca166b7a8398fa9961f # Parent 43bde39bbe659202cb149aec2d6b07d6d26fc107 topic: don't cache topic of e.g. memctx in _topiccache (issue6500) _topiccache exists to make us hit the storage less often when we want to look at topics for any reason. It doesn't make much sense to cache something that is memory-only and is cheap to access however. Caching things like that was also a source of a bug where creating multiple memctx instances in one process would cache topic of the first one and ignore actual content of .extra() of the others. That was happening because the cache is keyed by .rev(), but all memctx instances have the same .rev() = None. diff -r 43bde39bbe65 -r 6c67219ce779 CHANGELOG --- a/CHANGELOG Sun Aug 29 14:30:37 2021 +0300 +++ b/CHANGELOG Sun Aug 29 14:41:23 2021 +0300 @@ -4,6 +4,11 @@ 10.3.4 - in progress -------------------- +topic (0.22.4) + + * topic: don't cache .topic() of memctx instances, as that could produce + KeyError: b'topic' during some rewrite operations (issue6500) + 10.3.3 -- 2021-08-13 -------------------- diff -r 43bde39bbe65 -r 6c67219ce779 hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Sun Aug 29 14:30:37 2021 +0300 +++ b/hgext3rd/topic/__init__.py Sun Aug 29 14:41:23 2021 +0300 @@ -298,6 +298,9 @@ # topic loaded, but not enabled (eg: multiple repo in the same process) if cache is None: return b'' + if self.rev() is None: + # don't cache volatile ctx instances that aren't stored on-disk yet + return self.extra().get(constants.extrakey, b'') topic = cache.get(self.rev()) if topic is None: topic = self.extra().get(constants.extrakey, b'') diff -r 43bde39bbe65 -r 6c67219ce779 tests/test-topic-issue6500.t --- a/tests/test-topic-issue6500.t Sun Aug 29 14:30:37 2021 +0300 +++ b/tests/test-topic-issue6500.t Sun Aug 29 14:41:23 2021 +0300 @@ -32,14 +32,13 @@ 1: amend_source=* branch=default topic=foo (glob) 2: amend_source=* branch=default (glob) -TODO: creating and handling 2 memctx instances (based on 1 and then 2) should work +creating and handling 2 memctx instances (based on 1 and then 2) should work - $ hg touch --hidden -r 1+2 --duplicate 2>&1 | tail -2 - del ctx.extra()[constants.extrakey] - KeyError: b'topic' + $ hg touch --hidden -r 1+2 --duplicate + switching to topic foo -TODO: make sure extras stay the same +make sure extras stay the same $ hg log --hidden -r 3+4 -T '{rev}: {join(extras, " ")}\n' - abort: unknown revision '3' (glob) - [255] + 3: __touch-noise__=* amend_source=* branch=default topic=foo (glob) + 4: __touch-noise__=* amend_source=* branch=default (glob)