Patchwork D11982: stream-clone: only consider store requirements

login
register
mail settings
Submitter phabricator
Date Jan. 12, 2022, 2:11 p.m.
Message ID <differential-rev-PHID-DREV-vrmontl2qf6gwgcwv3s7-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50316/
State New
Headers show

Comments

phabricator - Jan. 12, 2022, 2:11 p.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  They are different kind of requirements, the one which impact the store and are
  relevant to the files being streamed and the one which does not. For example
  some requirements are only relevant to the working copy, like sparse, or
  dirstate-v2.
  
  Since they are irrelevant to the content being streamed, they should not
  prevent the receiving side to use streaming clone. So we no longer advertise
  them over the wire.
  
  In addition, the client side can decide to use whichever format it desire for
  the part that does not affect the store itself. So the configuration related to
  these format are not used when doing a streaming clone.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  mercurial/bundle2.py
  mercurial/streamclone.py
  mercurial/wireprotov1server.py
  tests/test-clone-stream.t

CHANGE DETAILS




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

Patch

diff --git a/tests/test-clone-stream.t b/tests/test-clone-stream.t
--- a/tests/test-clone-stream.t
+++ b/tests/test-clone-stream.t
@@ -905,3 +905,52 @@ 
   $ killdaemons.py
 
 #endif
+
+Stream clone regarding non-store format variant
+-----------------------------------------------
+
+  $ cat << EOF >> $HGRCPATH
+  > [storage]
+  > dirstate-v2.slow-path=allow
+  > EOF
+
+
+We can add dirstate-v2 when cloning (or any other non-store format change actually)
+
+  $ hg init server-no-dirstate-v2 --config format.exp-rc-dirstate-v2=no
+  $ hg debugbuilddag .+5 -R server-no-dirstate-v2
+  $ hg serve -p $HGPORT -d --pid-file=hg.pid -R server-no-dirstate-v2
+  $ cat hg.pid > $DAEMON_PIDS
+  $ hg debugcapabilities http://localhost:$HGPORT | grep streamreqs
+    streamreqs=generaldelta,revlogv1,sparserevlog (no-rust !)
+    streamreqs=generaldelta,persistent-nodemap,revlogv1,sparserevlog (rust !)
+  $ hg clone --quiet -U --stream --config format.exp-rc-dirstate-v2=yes http://localhost:$HGPORT clone-added-d2
+  $ hg debugrequirement -R server-no-dirstate-v2 | grep dirstate-v2
+  [1]
+  $ hg debugformat -R server-no-dirstate-v2 | grep dirstate-v2
+  dirstate-v2:         no
+  $ hg debugrequirement -R clone-added-d2 | grep dirstate-v2
+  dirstate-v2
+  $ hg debugformat -R clone-added-d2 | grep dirstate-v2
+  dirstate-v2:        yes
+  $ killdaemons.py
+
+We can drop it when cloning too.
+
+  $ hg init server-dirstate-v2 --config format.exp-rc-dirstate-v2=yes
+  $ hg debugbuilddag .+5 -R server-dirstate-v2
+  $ hg serve -p $HGPORT -d --pid-file=hg.pid -R server-dirstate-v2
+  $ cat hg.pid > $DAEMON_PIDS
+  $ hg debugcapabilities http://localhost:$HGPORT | grep streamreqs
+    streamreqs=generaldelta,revlogv1,sparserevlog (no-rust !)
+    streamreqs=generaldelta,persistent-nodemap,revlogv1,sparserevlog (rust !)
+  $ hg clone --quiet -U --stream --config format.exp-rc-dirstate-v2=no http://localhost:$HGPORT clone-dropped-d2
+  $ hg debugrequirement -R server-dirstate-v2 | grep dirstate-v2
+  dirstate-v2
+  $ hg debugformat -R server-dirstate-v2 | grep dirstate-v2
+  dirstate-v2:        yes
+  $ hg debugrequirement -R clone-dropped-d2 | grep dirstate-v2
+  [1]
+  $ hg debugformat -R clone-dropped-d2 | grep dirstate-v2
+  dirstate-v2:         no
+  $ killdaemons.py
diff --git a/mercurial/wireprotov1server.py b/mercurial/wireprotov1server.py
--- a/mercurial/wireprotov1server.py
+++ b/mercurial/wireprotov1server.py
@@ -301,6 +301,7 @@ 
         if repo.ui.configbool(b'server', b'preferuncompressed'):
             caps.append(b'stream-preferred')
         requiredformats = repo.requirements & repo.supportedformats
+        requiredformats -= requirementsmod.WORKING_DIR_REQUIREMENTS
         # if our local revlogs are just revlogv1, add 'stream' cap
         if not requiredformats - {requirementsmod.REVLOGV1_REQUIREMENT}:
             caps.append(b'stream')
diff --git a/mercurial/streamclone.py b/mercurial/streamclone.py
--- a/mercurial/streamclone.py
+++ b/mercurial/streamclone.py
@@ -184,13 +184,13 @@ 
 
     with repo.lock():
         consumev1(repo, fp, filecount, bytecount)
-
-        # new requirements = old non-format requirements +
-        #                    new format-related remote requirements
-        # requirements from the streamed-in repository
-        repo.requirements = requirements | (
-            repo.requirements - repo.supportedformats
-        )
+        # new requirements = old non-(store)-format requirements +
+        #                    new (store) format-related remote requirements
+        kept_requirements = set(repo.requirements)
+        kept_requirements -= repo.supportedformats
+        wc_req = requirementsmod.WORKING_DIR_REQUIREMENTS
+        kept_requirements |= repo.requirements & wc_req
+        repo.requirements = kept_requirements | set(requirements)
         repo.svfs.options = localrepo.resolvestorevfsoptions(
             repo.ui, repo.requirements, repo.features
         )
@@ -334,6 +334,7 @@ 
         raise ValueError(b'we do not support the compression argument yet')
 
     requirements = repo.requirements & repo.supportedformats
+    requirements -= requirementsmod.WORKING_DIR_REQUIREMENTS
     requires = b','.join(sorted(requirements))
 
     def gen():
@@ -797,12 +798,14 @@ 
 
     consumev2(repo, fp, filecount, filesize)
 
-    # new requirements = old non-format requirements +
-    #                    new format-related remote requirements
+    # new requirements = old non-(store)-format requirements +
+    #                    new (store) format-related remote requirements
     # requirements from the streamed-in repository
-    repo.requirements = set(requirements) | (
-        repo.requirements - repo.supportedformats
-    )
+    kept_requirements = set(repo.requirements)
+    kept_requirements -= repo.supportedformats
+    wc_req = requirementsmod.WORKING_DIR_REQUIREMENTS
+    kept_requirements |= repo.requirements & wc_req
+    repo.requirements = kept_requirements | set(requirements)
     repo.svfs.options = localrepo.resolvestorevfsoptions(
         repo.ui, repo.requirements, repo.features
     )
diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -1804,9 +1804,11 @@ 
     bundler.newpart(b'cache:rev-branch-cache', data=generate(), mandatory=False)
 
 
-def _formatrequirementsspec(requirements):
-    requirements = [req for req in requirements if req != b"shared"]
-    return urlreq.quote(b','.join(sorted(requirements)))
+def _formatrequirementsspec(requs):
+    requs = [
+        req for req in requs if req not in requirements.WORKING_DIR_REQUIREMENTS
+    ]
+    return urlreq.quote(b','.join(sorted(requs)))
 
 
 def _formatrequirementsparams(requirements):