Patchwork D11668: dirstate-v2: add an option to prevent unintentional slow dirstate-v2

login
register
mail settings
Submitter phabricator
Date Oct. 15, 2021, 2:09 a.m.
Message ID <differential-rev-PHID-DREV-wt2zbwrw65tymrjphdwz-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/49992/
State Superseded
Headers show

Comments

phabricator - Oct. 15, 2021, 2:09 a.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This is the project policy discussed in November 2020 and already put to use for
  the persistent nodemap.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11668

AFFECTED FILES
  mercurial/configitems.py
  mercurial/dirstate.py
  mercurial/localrepo.py
  tests/test-dirstate-race.t
  tests/test-dirstate-race2.t
  tests/test-dirstate.t
  tests/test-hgignore.t
  tests/test-permissions.t
  tests/test-purge.t
  tests/test-status.t
  tests/test-symlinks.t

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-symlinks.t b/tests/test-symlinks.t
--- a/tests/test-symlinks.t
+++ b/tests/test-symlinks.t
@@ -3,8 +3,12 @@ 
 #testcases dirstate-v1 dirstate-v2
 
 #if dirstate-v2
-  $ echo '[format]' >> $HGRCPATH
-  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > exp-dirstate-v2=1
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
 #endif
 
 == tests added in 0.7 ==
diff --git a/tests/test-status.t b/tests/test-status.t
--- a/tests/test-status.t
+++ b/tests/test-status.t
@@ -1,8 +1,12 @@ 
 #testcases dirstate-v1 dirstate-v2
 
 #if dirstate-v2
-  $ echo '[format]' >> $HGRCPATH
-  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > exp-dirstate-v2=1
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
 #endif
 
   $ hg init repo1
diff --git a/tests/test-purge.t b/tests/test-purge.t
--- a/tests/test-purge.t
+++ b/tests/test-purge.t
@@ -1,8 +1,12 @@ 
 #testcases dirstate-v1 dirstate-v2
 
 #if dirstate-v2
-  $ echo '[format]' >> $HGRCPATH
-  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > exp-dirstate-v2=1
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
 #endif
 
 init
diff --git a/tests/test-permissions.t b/tests/test-permissions.t
--- a/tests/test-permissions.t
+++ b/tests/test-permissions.t
@@ -3,8 +3,12 @@ 
 #testcases dirstate-v1 dirstate-v2
 
 #if dirstate-v2
-  $ echo '[format]' >> $HGRCPATH
-  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > exp-dirstate-v2=1
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
 #endif
 
   $ hg init t
diff --git a/tests/test-hgignore.t b/tests/test-hgignore.t
--- a/tests/test-hgignore.t
+++ b/tests/test-hgignore.t
@@ -1,8 +1,12 @@ 
 #testcases dirstate-v1 dirstate-v2
 
 #if dirstate-v2
-  $ echo '[format]' >> $HGRCPATH
-  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > exp-dirstate-v2=1
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
 #endif
 
   $ hg init ignorerepo
diff --git a/tests/test-dirstate.t b/tests/test-dirstate.t
--- a/tests/test-dirstate.t
+++ b/tests/test-dirstate.t
@@ -1,8 +1,12 @@ 
 #testcases dirstate-v1 dirstate-v2
 
 #if dirstate-v2
-  $ echo '[format]' >> $HGRCPATH
-  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > exp-dirstate-v2=1
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
 #endif
 
 ------ Test dirstate._dirs refcounting
diff --git a/tests/test-dirstate-race2.t b/tests/test-dirstate-race2.t
--- a/tests/test-dirstate-race2.t
+++ b/tests/test-dirstate-race2.t
@@ -1,8 +1,12 @@ 
 #testcases dirstate-v1 dirstate-v2
 
 #if dirstate-v2
-  $ echo '[format]' >> $HGRCPATH
-  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > exp-dirstate-v2=1
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
 #endif
 
 Checking the size/permissions/file-type of files stored in the
diff --git a/tests/test-dirstate-race.t b/tests/test-dirstate-race.t
--- a/tests/test-dirstate-race.t
+++ b/tests/test-dirstate-race.t
@@ -1,8 +1,12 @@ 
 #testcases dirstate-v1 dirstate-v2
 
 #if dirstate-v2
-  $ echo '[format]' >> $HGRCPATH
-  $ echo 'exp-dirstate-v2=1' >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > exp-dirstate-v2=1
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
 #endif
 
   $ hg init repo
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1174,6 +1174,32 @@ 
             if slow_path == b'abort':
                 raise error.Abort(msg, hint=hint)
         options[b'persistent-nodemap'] = True
+    if requirementsmod.DIRSTATE_V2_REQUIREMENT in requirements:
+        slow_path = ui.config(b'storage', b'dirstate-v2.slow-path')
+        if slow_path not in (b'allow', b'warn', b'abort'):
+            default = ui.config_default(b'storage', b'dirstate-v2.slow-path')
+            msg = _(b'unknown value for config "dirstate-v2.slow-path": "%s"\n')
+            ui.warn(msg % slow_path)
+            if not ui.quiet:
+                ui.warn(_(b'falling back to default value: %s\n') % default)
+            slow_path = default
+
+        msg = _(
+            b"accessing `dirstate-v2` repository without associated "
+            b"fast implementation."
+        )
+        hint = _(
+            b"check `hg help config.format.exp-dirstate-v2` " b"for details"
+        )
+        if not dirstate.HAS_FAST_DIRSTATE_V2:
+            if slow_path == b'warn':
+                msg = b"warning: " + msg + b'\n'
+                ui.warn(msg)
+                if not ui.quiet:
+                    hint = b'(' + hint + b')\n'
+                    ui.warn(hint)
+            if slow_path == b'abort':
+                raise error.Abort(msg, hint=hint)
     if ui.configbool(b'storage', b'revlog.persistent-nodemap.mmap'):
         options[b'persistent-nodemap.mmap'] = True
     if ui.configbool(b'devel', b'persistent-nodemap'):
diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -39,6 +39,8 @@ 
 parsers = policy.importmod('parsers')
 rustmod = policy.importrust('dirstate')
 
+HAS_FAST_DIRSTATE_V2 = rustmod is not None
+
 propertycache = util.propertycache
 filecache = scmutil.filecache
 _rangemask = dirstatemap.rangemask
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -1885,6 +1885,13 @@ 
     default=b'skip',
     experimental=True,
 )
+# experimental as long as format.exp-dirstate-v2 is.
+coreconfigitem(
+    b'storage',
+    b'dirstate-v2.slow-path',
+    default=b"abort",
+    experimental=True,
+)
 coreconfigitem(
     b'storage',
     b'new-repo-backend',