nodemap: gate the feature behind a new requirement
Now that the feature is working smoothly, a question was still open, should we
gate the feature behind a new requirement or just treat it as a cache to be
warmed by those who can and ignored by other.
The advantage of using the cache approach is a transparent upgrade/downgrade
story, making the feature easier to move to. However having out of date cache
can come with a significant performance hit for process who expect an up to
date cache but found none. In this case the file needs to be stored under
`.hg/cache`.
The "requirement" approach guarantee that the persistent nodemap is up to date.
However, it comes with a less flexible activation story since an explicite
upgrade is required. In this case the file can be stored in `.hg/store`.
This wiki page is relevant to this questions:
https://www.mercurial-scm.org/wiki/ComputedIndexPlan
So which one should we take? Another element came into plan, the persistent
nodemap use the `add` method of the transaction, it is used to keep track of a
file content before a transaction in case we need to rollback it back. It turns
out that the `transaction.add` API does not support file stored anywhere than
`.hg/store`. Making it support file stored elsewhere is possible, require a
change in on disk transaction format. Updating on disk file requires…
introducing a new requirements.
As a result, we pick the second option "gating the persistent nodemap behind a
new requirements".
Differential Revision: https://phab.mercurial-scm.org/D8417
$ hg init t
$ cd t
$ echo a > a
$ hg add a
$ hg commit -m test
$ rm .hg/requires
$ hg tip
abort: unknown version (2) in revlog 00changelog.i!
[255]
$ echo indoor-pool > .hg/requires
$ hg tip
abort: repository requires features unknown to this Mercurial: indoor-pool!
(see https://mercurial-scm.org/wiki/MissingRequirement for more information)
[255]
$ echo outdoor-pool >> .hg/requires
$ hg tip
abort: repository requires features unknown to this Mercurial: indoor-pool outdoor-pool!
(see https://mercurial-scm.org/wiki/MissingRequirement for more information)
[255]
$ cd ..
Test checking between features supported locally and ones required in
another repository of push/pull/clone on localhost:
$ mkdir supported-locally
$ cd supported-locally
$ hg init supported
$ echo a > supported/a
$ hg -R supported commit -Am '#0 at supported'
adding a
$ echo 'featuresetup-test' >> supported/.hg/requires
$ cat > $TESTTMP/supported-locally/supportlocally.py <<EOF
> from __future__ import absolute_import
> from mercurial import extensions, localrepo
> def featuresetup(ui, supported):
> for name, module in extensions.extensions(ui):
> if __name__ == module.__name__:
> # support specific feature locally
> supported |= {b'featuresetup-test'}
> return
> def uisetup(ui):
> localrepo.featuresetupfuncs.add(featuresetup)
> EOF
$ cat > supported/.hg/hgrc <<EOF
> [extensions]
> # enable extension locally
> supportlocally = $TESTTMP/supported-locally/supportlocally.py
> EOF
$ hg -R supported status
$ hg init push-dst
$ hg -R supported push push-dst
pushing to push-dst
abort: required features are not supported in the destination: featuresetup-test
[255]
$ hg init pull-src
$ hg -R pull-src pull supported
pulling from supported
abort: required features are not supported in the destination: featuresetup-test
[255]
$ hg clone supported clone-dst
abort: repository requires features unknown to this Mercurial: featuresetup-test!
(see https://mercurial-scm.org/wiki/MissingRequirement for more information)
[255]
$ hg clone --pull supported clone-dst
abort: required features are not supported in the destination: featuresetup-test
[255]
$ cd ..