diff --git a/.hgsigs b/.hgsigs
index 2c5ad5a5d29d60de06ca6073dae47d59365395db..319d2cb5d93a3dd41b75c49ceb1362a1919cad87 100644
--- a/.hgsigs
+++ b/.hgsigs
@@ -271,3 +271,5 @@ dc97e8670decc9925c2f570bdca636778184b199 0 iQHNBAABCgA3FiEEH2b4zfZU6QXBHaBhoR4Bz
 b267c5764cc6b804c619a42067405f27e8705beb 0 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
+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
diff --git a/.hgtags b/.hgtags
index 304245a0a02319408dadf6231e58991eb5e1de55..ad63a2bb7fa50acd03834dd83e7b108db49d3dd1 100644
--- a/.hgtags
+++ b/.hgtags
@@ -287,3 +287,5 @@ dc97e8670decc9925c2f570bdca636778184b199 6.9rc0
 b267c5764cc6b804c619a42067405f27e8705beb 6.9
 9751b9ccd74d8386687f88fbdfe280877840ec7d 6.9.1
 b964f92261d4fbb64f19aa6af2b072f7730b913a 6.9.2
+89ab2459f62ac8da3eb4f3ee2120d1814ce805d5 6.9.3
+ed68f9a47a090cc6450a7d5617baf123ba5fc42a 7.0rc0
diff --git a/PKG-INFO b/PKG-INFO
index 454f968faf7d0eee0b111380489a21ce8919523f..e33bed13cc38ca16831119bc13ad41f3d5843d72 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.2
 Name: mercurial
-Version: 7.0rc0
+Version: 7.0rc1
 Summary: Fast scalable distributed SCM (revision control, version control) system
 Author-email: Olivia Mackall and many others <mercurial@mercurial-scm.org>
 License: GNU GPLv2 or any later version
diff --git a/contrib/heptapod-ci.yml b/contrib/heptapod-ci.yml
index 3699ce0e90a57c124c2768547dc0f6a93662f5f0..62f58f42014b0bc41856d377c4844594ce52e7af 100644
--- a/contrib/heptapod-ci.yml
+++ b/contrib/heptapod-ci.yml
@@ -8,7 +8,7 @@
 # has succeeded.
 workflow:
   rules:
-    - if: $CI_COMMIT_BRANCH =~ /^branch\/.*/ && $CI_PIPELINE_SOURCE !~ "/web|schedule/"
+    - if: ($CI_COMMIT_BRANCH =~ /^branch\/.*/ || $CI_COMMIT_TAG) && $CI_PIPELINE_SOURCE !~ "/web|schedule/"
       when: never
     - if: $CI_PIPELINE_SOURCE == "merge_request_event"
       when: never
@@ -82,9 +82,9 @@ trigger-nightly-build:
   extends: .trigger
   stage: nightly-trigger
   rules:
-    - if: $CI_COMMIT_BRANCH =~ $RE_BRANCH && $CI_PIPELINE_SOURCE == "schedule"
+    - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)  && $CI_PIPELINE_SOURCE == "schedule"
       when: always
-    - if: $CI_COMMIT_BRANCH =~ $RE_BRANCH
+    - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)
       when: manual
       allow_failure: true
     - if: $CI_COMMIT_BRANCH =~ $RE_TOPIC
@@ -136,7 +136,7 @@ build-rust-wheel:
   extends: .trigger
   stage: build
   rules:
-  - if: $CI_COMMIT_BRANCH =~ $RE_BRANCH
+  - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)
     when: never
   - if: $CI_COMMIT_BRANCH =~ $RE_TOPIC
     when: manual
@@ -145,7 +145,7 @@ build-rust-wheel:
 .extra-c-wheel:
   extends: build-c-wheel
   rules:
-  - if: $CI_COMMIT_BRANCH =~ $RE_BRANCH
+  - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)
     needs:
       - trigger-nightly-build
   - if: $CI_COMMIT_BRANCH =~ $RE_TOPIC
@@ -335,7 +335,7 @@ trigger-pycompat:
   extends: .trigger
   stage: py-version-compat
   rules:
-  - if: $CI_COMMIT_BRANCH =~ $RE_BRANCH
+  - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)
     when: on_success
     needs:
       - trigger-nightly-build
@@ -441,7 +441,7 @@ trigger-wheel-windows:
   extends: .trigger
   stage: build
   rules:
-  - if: $CI_COMMIT_BRANCH =~ $RE_BRANCH
+  - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)
     when: never
   - if: $CI_COMMIT_BRANCH =~ $RE_TOPIC
     when: manual
@@ -454,7 +454,7 @@ build-c-wheel-windows:
     when: on_success
     needs:
     rules:
-    - if: $CI_COMMIT_BRANCH =~ $RE_BRANCH
+    - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)
       needs:
         - trigger-nightly-build
     - if: $CI_COMMIT_BRANCH =~ $RE_TOPIC
@@ -577,7 +577,7 @@ macos:
 # multiple jobs. (all this might be unnecessary)
 build-c-wheel-macos:
     rules:
-    - if: $CI_COMMIT_BRANCH =~ $RE_BRANCH
+    - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)
       needs:
         - trigger-nightly-build
     - if: $CI_COMMIT_BRANCH =~ $RE_TOPIC
@@ -609,7 +609,7 @@ build-c-wheel-macos:
   extends: .all
   stage: upload
   rules:
-    - if: '$CI_COMMIT_BRANCH =~ $RE_BRANCH'
+    - if: ($CI_COMMIT_BRANCH =~ $RE_BRANCH || $CI_COMMIT_TAG)
       # note that at the time of writing this, this job depends on multiple
       # manual one. So it will not run by default, but will automatically run
       # if the manual jobs are triggered.
@@ -702,5 +702,6 @@ upload-wheel-nightly:
       upload
       --verbose
       --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi
+      --skip-existing
       wheels/*/*/*/*.whl
       wheels/*/*.whl
diff --git a/contrib/win32/ReadMe.html b/contrib/win32/ReadMe.html
index 0caba51f84291776467f816599799254eefc6b48..2d21c249f0b3074420361d312d175b8e30152670 100644
--- a/contrib/win32/ReadMe.html
+++ b/contrib/win32/ReadMe.html
@@ -124,7 +124,7 @@ editor = whatever
 
     <p>
       If you are IRC-savvy, that's usually the fastest way to get
-      help. Go to <tt>#mercurial</tt> on <tt>libra.chat</tt>.
+      help. Go to <tt>#mercurial</tt> on <tt>libera.chat</tt>.
     </p>
 
     <h1>Author and copyright information</h1>
diff --git a/hgext/clonebundles.py b/hgext/clonebundles.py
index 2ffe29b55cf0d6d65c8ec7095092017df4ad43c5..f432ad04624fcfeb17ab3725d74c2da082d38706 100644
--- a/hgext/clonebundles.py
+++ b/hgext/clonebundles.py
@@ -1029,8 +1029,10 @@ def cmd_admin_clone_bundles_refresh(
     details about how to configure this feature.
     """
     debug = repo.ui.configbool(b'devel', b'debug.clonebundles')
+    op_id = repo.ui.config(b'devel', b'clonebundles.override-operation-id')
     bundles = read_auto_gen(repo)
-    op_id = b"%d_acbr" % os.getpid()
+    if op_id is None:
+        op_id = b"%d_acbr" % os.getpid()
     create, delete = auto_bundle_needed_actions(repo, bundles, op_id)
 
     # if some bundles are scheduled for creation in the background, they will
diff --git a/mercurial.egg-info/PKG-INFO b/mercurial.egg-info/PKG-INFO
index 454f968faf7d0eee0b111380489a21ce8919523f..e33bed13cc38ca16831119bc13ad41f3d5843d72 100644
--- a/mercurial.egg-info/PKG-INFO
+++ b/mercurial.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.2
 Name: mercurial
-Version: 7.0rc0
+Version: 7.0rc1
 Summary: Fast scalable distributed SCM (revision control, version control) system
 Author-email: Olivia Mackall and many others <mercurial@mercurial-scm.org>
 License: GNU GPLv2 or any later version
diff --git a/mercurial.egg-info/SOURCES.txt b/mercurial.egg-info/SOURCES.txt
index ea676ea8753c9f3c3edbf57e6c113083a694dcff..602118479eddb56a08da5330a22da38716c7df35 100644
--- a/mercurial.egg-info/SOURCES.txt
+++ b/mercurial.egg-info/SOURCES.txt
@@ -1593,6 +1593,7 @@ tests/test-bundle2-format.t
 tests/test-bundle2-multiple-changegroups.t
 tests/test-bundle2-pushback.t
 tests/test-bundle2-remote-changegroup.t
+tests/test-bundle2.py
 tests/test-byteify-strings.t
 tests/test-cache-abuse.t
 tests/test-cappedreader.py
diff --git a/mercurial/__version__.py b/mercurial/__version__.py
index dad81e9138c19cc178f1733e053ae5556160ebfd..a86f8ce69c7f9b34f96a8866e3279aab7c202e93 100644
--- a/mercurial/__version__.py
+++ b/mercurial/__version__.py
@@ -17,5 +17,5 @@ __version__: str
 __version_tuple__: VERSION_TUPLE
 version_tuple: VERSION_TUPLE
 
-__version__ = version = '7.0rc0'
+__version__ = version = '7.0rc1'
 __version_tuple__ = version_tuple = (7, 0)
diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
index 06f616483cb1401cdfab04623b32d8a96f05d10c..c31e6fcc87641a7bd77aaa5ec0696394bb09b201 100644
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -939,7 +939,16 @@ class unbundle20(unpackermixin):
             yield _pack(_fstreamparamsize, paramssize)
         # From there, payload might need to be decompressed
         self._fp = self._compengine.decompressorreader(self._fp)
-        emptycount = 0
+
+        # We usually wait for empty terminators: a bundle part terminator
+        # followed by a bundle terminator.
+        #
+        # Since the empty bundle has no parts,
+        # bundle part terminator never comes.
+        #
+        # So we boostrap this detection with am empty part, which the first
+        # piece of part will reset.
+        emptycount = 1
         while emptycount < 2:
             # so we can brainlessly loop
             assert _fpartheadersize == _fpayloadsize
diff --git a/mercurial/bundlecaches.py b/mercurial/bundlecaches.py
index 14a8e83420760535437b1e7a590bb5798803ca0e..3a738b89339fa25051320ef7f25cd703a64c2fb0 100644
--- a/mercurial/bundlecaches.py
+++ b/mercurial/bundlecaches.py
@@ -102,8 +102,12 @@ class bundlespec:
 
     def as_spec(self):
         parts = [b"%s-%s" % (self.compression, self.version)]
-        for param in sorted(self._explicit_params.items()):
-            parts.append(b'%s=%s' % param)
+        for param, raw_value in sorted(self._explicit_params.items()):
+            if isinstance(raw_value, bool):
+                value = b"yes" if raw_value else b"no"
+            else:
+                value = raw_value
+            parts.append(b'%s=%s' % (param, value))
         return b';'.join(parts)
 
 
@@ -322,11 +326,18 @@ def parsebundlespec(repo, spec, strict=True):
     # repo supports and error if the bundle isn't compatible.
     if b'requirements' in params:
         requirements = set(cast(bytes, params[b'requirements']).split(b','))
-        missingreqs = requirements - requirementsmod.STREAM_FIXED_REQUIREMENTS
-        if missingreqs:
+        relevant_reqs = (
+            requirements - requirementsmod.STREAM_IGNORABLE_REQUIREMENTS
+        )
+        # avoid cycle (not great for pytype)
+        from . import localrepo
+
+        supported_req = localrepo.gathersupportedrequirements(repo.ui)
+        missing_reqs = relevant_reqs - supported_req
+        if missing_reqs:
             raise error.UnsupportedBundleSpecification(
                 _(b'missing support for repository features: %s')
-                % b', '.join(sorted(missingreqs))
+                % b', '.join(sorted(missing_reqs))
             )
 
     # Compute contentopts based on the version
diff --git a/mercurial/configitems.toml b/mercurial/configitems.toml
index ef3e530e9fe955029067a562deac1c0d7e62322e..52662f3bc716d1d9d7b0a220cfb40e2a5214219e 100644
--- a/mercurial/configitems.toml
+++ b/mercurial/configitems.toml
@@ -463,6 +463,15 @@ default = false
 section = "devel"
 name = "cache-vfs"
 
+[[items]]
+section = "devel"
+name = "clonebundles.override-operation-id"
+documentation = """
+override the operation id used to produce unique filename at generation time.
+
+Useful to stabilize some filename in the tests.
+"""
+
 [[items]]
 section = "devel"
 name = "check-locks"
@@ -2979,8 +2988,8 @@ bundle.
 When set to 0, the default, the value used depends on the value of the
 `usage.resources.cpu` configuration:
 - low:    1 writer
-- medium: 2 writers (default)
-- high:   4 writers
+- medium: 4 writers (default)
+- high:   8 writers
 """
 
 [[items]]
@@ -2994,8 +3003,8 @@ If set to a negative value, the amount of memory used will not be restricted.
 
 When set to 0, the default value depends on the `usage.resources.memory` value.
 - low:    100 MB,
-- medium:   1 GB,
-- high:   unrestricted memory usage.
+- medium: 500 MB,
+- high:     2 GB
 """
 
 
diff --git a/mercurial/requirements.py b/mercurial/requirements.py
index ecf2338692d9da969eb8c703fb8810501392ccb6..4afe5f918a2e4e9b8f9eb942e4ea4f05f3820c0e 100644
--- a/mercurial/requirements.py
+++ b/mercurial/requirements.py
@@ -105,22 +105,13 @@ WORKING_DIR_REQUIREMENTS = {
     DIRSTATE_V2_REQUIREMENT,
 }
 
-# List of requirement that impact "stream-clone" (and hardlink clone) and
-# cannot be changed in such cases.
+# List of requirement that do not impact "stream-clone" (and hardlink clone) and
+# can be ignored in such case.
 #
-# requirements not in this list are safe to be altered during stream-clone.
-#
-# note: the list is currently inherited from previous code and miss some relevant requirement while containing some irrelevant ones.
-STREAM_FIXED_REQUIREMENTS = {
-    ARCHIVED_PHASE_REQUIREMENT,
-    BOOKMARKS_IN_STORE_REQUIREMENT,
-    CHANGELOGV2_REQUIREMENT,
-    COPIESSDC_REQUIREMENT,
-    GENERALDELTA_REQUIREMENT,
-    INTERNAL_PHASE_REQUIREMENT,
-    REVLOG_COMPRESSION_ZSTD,
-    REVLOGV1_REQUIREMENT,
-    REVLOGV2_REQUIREMENT,
-    SPARSEREVLOG_REQUIREMENT,
-    TREEMANIFEST_REQUIREMENT,
+# requirements not in this list safe to be altered during stream-clone.
+STREAM_IGNORABLE_REQUIREMENTS = WORKING_DIR_REQUIREMENTS | {
+    DOTENCODE_REQUIREMENT,  # abstracted by the vfs layer
+    FNCACHE_REQUIREMENT,  # abstracted by the vfs layer
+    STORE_REQUIREMENT,  # abstracted by the vfs layer
+    NODEMAP_REQUIREMENT,  # Have some special logic to handle that case
 }
diff --git a/mercurial/streamclone.py b/mercurial/streamclone.py
index 65fcf717150d0378bfdfb5e126e9a55fdeafdcf5..eb2d07e8e0637408c682c9c84aa57e58e36cd296 100644
--- a/mercurial/streamclone.py
+++ b/mercurial/streamclone.py
@@ -75,7 +75,7 @@ def new_stream_clone_requirements(
     configuration choice when possible.
     """
     requirements = set(default_requirements)
-    requirements -= requirementsmod.STREAM_FIXED_REQUIREMENTS
+    requirements & requirementsmod.STREAM_IGNORABLE_REQUIREMENTS
     requirements.update(streamed_requirements)
     return requirements
 
@@ -86,7 +86,7 @@ def streamed_requirements(repo) -> Set[bytes]:
     This is used for advertising the stream options and to generate the actual
     stream content."""
     requiredformats = (
-        repo.requirements & requirementsmod.STREAM_FIXED_REQUIREMENTS
+        repo.requirements - requirementsmod.STREAM_IGNORABLE_REQUIREMENTS
     )
     return requiredformats
 
diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py
index 062218e82ab1e8dc3b27f7f68cb60efb27f7432e..0dbaa1cd2ab7f3bc53ea0166ee5ccc4432c00161 100644
--- a/mercurial/utils/procutil.py
+++ b/mercurial/utils/procutil.py
@@ -743,7 +743,7 @@ else:
             script = b' '.join(shellquote(x) for x in cmd)
         if record_wait is None:
             # double-fork to completely detach from the parent process
-            script = b'( %s ) &' % script
+            script = b'( ( %s ) <&3 3<&- &) 3<&0' % script
             start_new_session = True
         else:
             start_new_session = False
diff --git a/mercurial/vfs.py b/mercurial/vfs.py
index 7ca7b411920035e21dc650ffa9215d48d6f9ec61..eebb5892a1119d0773e7f9733ba8050bf8f2f08a 100644
--- a/mercurial/vfs.py
+++ b/mercurial/vfs.py
@@ -476,9 +476,9 @@ class abstractvfs(abc.ABC):
             <path> is the real file system path content should be written to,
             <mode> is the file mode that need to be set if any.
         """
-        self._auditpath(path, b'wb')
-        self.register_file(path)
         real_path = self.join(path)
+        self._auditpath(real_path, b'wb')
+        self.register_file(path)
         dirname, basename = util.split(real_path)
         if dirname not in known_directories:
             util.makedirs(dirname, self.createmode, True)
diff --git a/relnotes/7.0 b/relnotes/7.0
index 164d03f2a79ab05338d3bb8cebf9120c98212412..32def3ceb8650b55cb45f5f058eb271fdd887277 100644
--- a/relnotes/7.0
+++ b/relnotes/7.0
@@ -53,6 +53,9 @@ We now use `BuildTools 2022` when building Windows packages.
 - rhg: set the expected dirstate permissions (0o666 minus umask) (a48c688d3e80)
 - rhg: fix matcher issue (136e74c2bf8f)
 - rhg files correctly implements `--rev` (it instead provided `--revision`)
+- clone-bundles: fix background spawning of automatic generation
+- bundle-spec: properly format boolean parameter (issue6960)
+- bundle2: fix a bug where _forwardchunks doesn't work with empty bundles
 
 == Rust ==
 
diff --git a/rust/hg-core/src/vfs.rs b/rust/hg-core/src/vfs.rs
index 3b7391978d66b5daa288fe68d96d3f76771981df..25f909fefca3a3e57d8a9d75c678736c40d260b7 100644
--- a/rust/hg-core/src/vfs.rs
+++ b/rust/hg-core/src/vfs.rs
@@ -929,7 +929,7 @@ impl Vfs for FnCacheVfs {
 /// a local clone, and we don't want to modify the original repo.
 fn copy_in_place_if_hardlink(path: &Path) -> Result<(), HgError> {
     let metadata = path.metadata().when_writing_file(path)?;
-    if metadata.nlink() > 0 {
+    if metadata.nlink() > 1 {
         // If it's hardlinked, copy it and rename it back before changing it.
         let tmpdir = path.parent().expect("file at root");
         let name = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
diff --git a/tests/drawdag.py b/tests/drawdag.py
index a88b2351551156c22c84747d7597d19f9ebf036b..5085af48a7c0df80e036740b287aced9a43d3b19 100644
--- a/tests/drawdag.py
+++ b/tests/drawdag.py
@@ -79,6 +79,20 @@ Some special comments could have side effects:
       # replace: A -> B -> C -> D  # chained 1 to 1 replacements
       # split: A -> B, C           # 1 to many
       # prune: A, B, C             # many to nothing
+
+Special comment can also be used to control file content for some revision.
+
+The example below create two extra files in A, update on in B and delete the
+other on in C (using a special content to mark the deletion).
+
+In all case the file matching the node name is created for all non-merge
+commit.
+
+    C # A/file/path=content in A
+    | # A/other/file/path=content for another file
+    B # B/file/path=updated content in B
+    | # C/other/file/path=<deleted>
+    A
 """
 
 import collections
@@ -300,7 +314,10 @@ class simplecommitctx(context.committablectx):
             self._parents.append(repo[repo.nullid])
 
     def filectx(self, key):
-        return simplefilectx(key, self._added[key])
+        content = self._added.get(key)
+        if content is not None:
+            return simplefilectx(key, content)
+        return None
 
     def commit(self):
         return self._repo.commitctx(self)
@@ -381,10 +398,13 @@ def debugdrawdag(ui, repo, **opts):
     # parse comments to get extra file content instructions
     files = collections.defaultdict(dict)  # {(name, path): content}
     comments = list(_getcomments(text))
-    filere = re.compile(br'^(\w+)/([\w/]+)\s*=\s*(.*)$', re.M)
+    filere = re.compile(br'^(\w+)/([-_\w/"]+)\s*=\s*(.*)$', re.M)
     for name, path, content in filere.findall(b'\n'.join(comments)):
         content = content.replace(br'\n', b'\n').replace(br'\1', b'\1')
-        files[name][path] = content
+        if content == b"<deleted>":
+            files[name][path] = None
+        else:
+            files[name][path] = content
 
     committed = {None: repo.nullid}  # {name: node}
 
diff --git a/tests/hghave.py b/tests/hghave.py
index 244d56312be32f7289034b6a3020f6456c67402f..fe8f55901fe0de6ce86dca97f7c611602b2cee6f 100644
--- a/tests/hghave.py
+++ b/tests/hghave.py
@@ -666,7 +666,9 @@ def getpygmentsversion():
         return 0, 0
 
 
-@checkvers("pygments", "Pygments version >= %s", ('2.5', '2.11', '2.14'))
+@checkvers(
+    "pygments", "Pygments version >= %s", ('2.5', '2.11', '2.14', '2.19')
+)
 def has_pygments_range(v):
     major, minor = v.split('.')[0:2]
     return getpygmentsversion() >= (int(major), int(minor))
diff --git a/tests/test-bundle2.py b/tests/test-bundle2.py
new file mode 100644
index 0000000000000000000000000000000000000000..271466fd170c66e1ce2135e21f542d03f58374cb
--- /dev/null
+++ b/tests/test-bundle2.py
@@ -0,0 +1,33 @@
+import unittest
+from mercurial import bundle2, ui as uimod
+
+bundle20 = bundle2.bundle20
+unbundle20 = bundle2.unbundle20
+
+ui = uimod.ui.load()
+
+
+class Bundle2tests(unittest.TestCase):
+    def test_nonempty_bundle_forwardchunks(self):
+        bundler = bundle20(ui)
+        bundler.newpart(
+            b'cache:rev-branch-cache', data=b'some-data', mandatory=False
+        )
+        data = b''.join(list(bundler.getchunks()))
+        unbundle = unbundle20(ui, __import__("io").BytesIO(data[4:]))
+        forwarded_data = b''.join(list(unbundle._forwardchunks()))
+        self.assertEqual(data, forwarded_data)
+
+    def test_empty_bundle_forwardchunks(self):
+        bundler = bundle20(ui)
+        data = b''.join(list(bundler.getchunks()))
+        self.assertEqual(data, b'HG20\0\0\0\0\0\0\0\0')
+        unbundle = unbundle20(ui, __import__("io").BytesIO(data[4:]))
+        forwarded_data = b''.join(list(unbundle._forwardchunks()))
+        self.assertEqual(data, forwarded_data)
+
+
+if __name__ == '__main__':
+    import silenttestrunner
+
+    silenttestrunner.main(__name__)
diff --git a/tests/test-clonebundles-autogen.t b/tests/test-clonebundles-autogen.t
index f7d4a8b1910315bb550a54411570eac7349173dd..aed423319832b78742d142382a1e22be83fac961 100644
--- a/tests/test-clonebundles-autogen.t
+++ b/tests/test-clonebundles-autogen.t
@@ -411,12 +411,76 @@ bundles should have been generated
   full-bzip2-v2-11_revs-4226b1cd5fda_tip-*_acbr.hg (glob)
   $ ls -1 ../server/.hg/tmp-bundles
 
-Test HTTP URL
-=========================
+background generation without debug
+-----------------------------------
+
+The debug option make the command wait for background process and change the
+way stdin is accessible to the script. So we also test this variant.
+
+Gather the name of the expected bundle
+
+  $ v1_file=$TESTTMP/final-upload/full-bzip2-v1-11_revs-4226b1cd5fda_tip-background_testing.hg
+  $ v2_file=$TESTTMP/final-upload/full-bzip2-v2-11_revs-4226b1cd5fda_tip-background_testing.hg
+
+cleanup things
+
 
   $ hg -R ../server/ admin::clone-bundles-clear
   clone-bundles: deleting bundle full-bzip2-v1-11_revs-4226b1cd5fda_tip-*_acbr.hg (glob)
   clone-bundles: deleting bundle full-bzip2-v2-11_revs-4226b1cd5fda_tip-*_acbr.hg (glob)
+(also delete the manifest to be sure)
+  $ rm ../server/.hg/clonebundles.manifest
+
+Nothing should remain
+
+  $ cat ../server/.hg/clonebundles.auto-gen
+  $ ls -1 ../final-upload
+  $ ls -1 ../server/.hg/tmp-bundles
+
+Start a process in the background without the debug option
+
+  $ hg -R ../server/ admin::clone-bundles-refresh --background \
+  >     --config devel.debug.clonebundles=no \
+  >     --config devel.clonebundles.override-operation-id=background_testing
+
+  $ $RUNTESTDIR/testlib/wait-on-file 30 $v1_file
+  $ $RUNTESTDIR/testlib/wait-on-file 30 $v2_file
+
+all file created, but some cleanup might still be in progress, we wait 30 second for them
+
+# note: we should adjust that timing according to the test timeout, but that is more a
+#       change for the default branch than the stable branch
+
+  $ for x in `$RUNTESTDIR/seq.py 30`; do
+  >      if grep --invert-match DONE ../server/.hg/clonebundles.auto-gen > /dev/null; then
+  >          # some task still running
+  >          sleep 1
+  >          continue
+  >      fi
+  >      # all task are done running
+  >      break
+  > done
+
+We should have bundle now
+
+  $ cat ../server/.hg/clonebundles.manifest
+  file:/*/$TESTTMP/final-upload/full-bzip2-v1-11_revs-4226b1cd5fda_tip-background_testing.hg BUNDLESPEC=bzip2-v1 (glob)
+  file:/*/$TESTTMP/final-upload/full-bzip2-v2-11_revs-4226b1cd5fda_tip-background_testing.hg BUNDLESPEC=bzip2-v2 (glob)
+  $ ls -1 ../final-upload
+  full-bzip2-v1-11_revs-4226b1cd5fda_tip-background_testing.hg
+  full-bzip2-v2-11_revs-4226b1cd5fda_tip-background_testing.hg
+  $ ls -1 ../server/.hg/tmp-bundles
+
+
+
+
+
+Test HTTP URL
+=========================
+
+  $ hg -R ../server/ admin::clone-bundles-clear
+  clone-bundles: deleting bundle full-bzip2-v1-11_revs-4226b1cd5fda_tip-*.hg (glob)
+  clone-bundles: deleting bundle full-bzip2-v2-11_revs-4226b1cd5fda_tip-*.hg (glob)
 
   $ cat >> ../server/.hg/hgrc << EOF
   > [clone-bundles]
@@ -526,6 +590,7 @@ check first regeneration (should cleanup the one before that last)
   full-bzip2-v2-13_revs-8a81f9be54ea_tip-*_acbr.hg (glob)
   full-bzip2-v2-15_revs-17615b3984c2_tip-*_acbr.hg (glob)
   $ ls -1 ../final-upload
+  $ cd ..
 
 Check the url is correct
 ------------------------
@@ -540,3 +605,44 @@ Check the url is correct
   searching for changes
   no changes found
   15 local changesets published
+
+Test spec with boolean component (issue6960)
+============================================
+
+  $ cat >> ./server/.hg/hgrc << EOF
+  > [clone-bundles]
+  > auto-generate.formats = gzip-v2;obsolescence=yes,gzip-v3;obsolescence=no,gzip-v3;obsolescence=yes;obsolescence-mandatory=no
+  > EOF
+
+  $ rm ./server/.hg/clonebundles.manifest
+  $ hg -R ./server/ admin::clone-bundles-refresh
+  clone-bundles: deleting inline bundle full-bzip2-v1-13_revs-8a81f9be54ea_tip-*_acbr.hg (glob)
+  clone-bundles: deleting inline bundle full-bzip2-v2-13_revs-8a81f9be54ea_tip-*_acbr.hg (glob)
+  clone-bundles: starting bundle generation: gzip-v2;obsolescence=yes
+  15 changesets found
+  clone-bundles: starting bundle generation: gzip-v3;obsolescence=no
+  15 changesets found
+  clone-bundles: starting bundle generation: gzip-v3;obsolescence=yes;obsolescence-mandatory=no
+  15 changesets found
+  $ cat ./server/.hg/clonebundles.manifest
+  peer-bundle-cache://full-bzip2-v1-15_revs-17615b3984c2_tip-*_acbr.hg BUNDLESPEC=bzip2-v1 (glob)
+  peer-bundle-cache://full-bzip2-v2-15_revs-17615b3984c2_tip-*_acbr.hg BUNDLESPEC=bzip2-v2 (glob)
+  peer-bundle-cache://full-gzip-v2;obsolescence=yes-15_revs-17615b3984c2_tip-*_acbr.hg BUNDLESPEC=gzip-v2;obsolescence=yes (glob)
+  peer-bundle-cache://full-gzip-v3;obsolescence=no-15_revs-17615b3984c2_tip-*_acbr.hg BUNDLESPEC=gzip-v3;obsolescence=no (glob)
+  peer-bundle-cache://full-gzip-v3;obsolescence=yes;obsolescence-mandatory=no-15_revs-17615b3984c2_tip-*_acbr.hg BUNDLESPEC=gzip-v3;obsolescence=yes;obsolescence-mandatory=no (glob)
+
+
+Check the manifest is correct
+-----------------------------
+
+  $ hg clone -U ssh://user@dummy/server ssh-inline-more-param-clone
+  applying clone bundle from peer-bundle-cache://full-bzip2-v1-15_revs-17615b3984c2_tip-*_acbr.hg (glob)
+  adding changesets
+  adding manifests
+  adding file changes
+  added 15 changesets with 15 changes to 15 files
+  finished applying clone bundle
+  searching for changes
+  no changes found
+  15 local changesets published
+
diff --git a/tests/test-drawdag.t b/tests/test-drawdag.t
index 1b040a65a928b5f716fef9ea83f04d275f3d0692..949f6f084ef28c758bdb69102af0d7e7ace8a0b3 100644
--- a/tests/test-drawdag.t
+++ b/tests/test-drawdag.t
@@ -242,17 +242,50 @@ Change file contents via comments
   > |\      # B/dir2/b = 34
   > A B     # C/dir1/c = 5
   >         # C/dir2/c = 6
+  >         # A/to-be"deleted" = I am doomed.
+  >         # B/to-be-deleted_too = The end is near.
+  >         # C/to-be"deleted"=<deleted>
+  >         # C/to-be-deleted_too = <deleted>
   >         # C/A = a
   >         # C/B = b
   > EOS
 
   $ hg log -G -T '{desc} {files}'
-  o    C A B dir1/c dir2/c
+  o    C A B dir1/c dir2/c to-be"deleted" to-be-deleted_too
   |\
-  | o  B B dir2/b
+  | o  B B dir2/b to-be-deleted_too
   |
-  o  A A dir1/a
+  o  A A dir1/a to-be"deleted"
   
+  $ for r in `hg log -T '{rev} ' --rev "sort(all())"`; do
+  >     hg log --rev $r -T "### {tags} ###\n";
+  >     hg diff --change $r --stat;
+  > done
+  ### A ###
+   A              |  1 +
+   dir1/a         |  2 ++
+   to-be"deleted" |  1 +
+   3 files changed, 4 insertions(+), 0 deletions(-)
+  ### B ###
+   B                 |  1 +
+   dir2/b            |  1 +
+   to-be-deleted_too |  1 +
+   3 files changed, 3 insertions(+), 0 deletions(-)
+  ### C tip ###
+   A              |  2 +-
+   B              |  1 +
+   dir1/c         |  1 +
+   dir2/b         |  1 +
+   dir2/c         |  1 +
+   to-be"deleted" |  1 -
+   6 files changed, 5 insertions(+), 2 deletions(-)
+  $ hg files -r C
+  A
+  B
+  dir1/a
+  dir1/c
+  dir2/b
+  dir2/c
   $ for f in `hg files -r C`; do
   >   echo FILE "$f"
   >   hg cat -r C "$f"
diff --git a/tests/test-highlight.t b/tests/test-highlight.t
index 45b7b3c1398260c0a7c492e2f775377e8ac6b55f..2dc9f86a03c992d7f8edbd3e93a92228648cfd6d 100644
--- a/tests/test-highlight.t
+++ b/tests/test-highlight.t
@@ -160,12 +160,15 @@ hgweb filerevision, html
   <span id="l4"><span class="sd">    where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span></span><a href="#l4"></a>
   <span id="l5"><span class="sd">&quot;&quot;&quot;</span></span><a href="#l5"></a>
   <span id="l6"></span><a href="#l6"></a>
-  <span id="l7"><span class="kn">import</span> <span class="nn">itertools</span></span><a href="#l7"></a>
+  <span id="l7"><span class="kn">import</span><span class="w"> </span><span class="nn">itertools</span></span><a href="#l7"></a> (pygments219 !)
+  <span id="l7"><span class="kn">import</span> <span class="nn">itertools</span></span><a href="#l7"></a> (no-pygments219 !)
   <span id="l8"></span><a href="#l8"></a>
-  <span id="l9"><span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></span><a href="#l9"></a>
+  <span id="l9"><span class="kn">def</span><span class="w"> </span><span class="nf">primes</span><span class="p">():</span></span><a href="#l9"></a> (pygments219 !)
+  <span id="l9"><span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></span><a href="#l9"></a> (no-pygments219 !)
   <span id="l10"><span class="w">    </span><span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span></span><a href="#l10"></a> (pygments214 !)
   <span id="l10">    <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span></span><a href="#l10"></a> (no-pygments214 !)
-  <span id="l11">    <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></span><a href="#l11"></a>
+  <span id="l11">    <span class="kn">def</span><span class="w"> </span><span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></span><a href="#l11"></a> (pygments219 !)
+  <span id="l11">    <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></span><a href="#l11"></a> (no-pygments219 !)
   <span id="l12">        <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></span><a href="#l12"></a>
   <span id="l13">        <span class="c"># It is important to yield *here* in order to stop the</span></span><a href="#l13"></a>
   <span id="l14">        <span class="c"># infinite recursion.</span></span><a href="#l14"></a>
@@ -179,7 +182,8 @@ hgweb filerevision, html
   <span id="l22">    <span class="kn">return</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></span><a href="#l22"></a>
   <span id="l23"></span><a href="#l23"></a>
   <span id="l24"><span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span></span><a href="#l24"></a>
-  <span id="l25">    <span class="kn">import</span> <span class="nn">sys</span></span><a href="#l25"></a>
+  <span id="l25">    <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span></span><a href="#l25"></a> (pygments219 !)
+  <span id="l25">    <span class="kn">import</span> <span class="nn">sys</span></span><a href="#l25"></a> (no-pygments219 !)
   <span id="l26">    <span class="kn">try</span><span class="p">:</span></span><a href="#l26"></a>
   <span id="l27">        <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></span><a href="#l27"></a>
   <span id="l28">    <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></span><a href="#l28"></a>
@@ -439,7 +443,8 @@ hgweb fileannotate, html
   <a href="/rev/687f2d169546">changeset</a>
   </div>
   </td>
-  <td class="source followlines-btn-parent"><a href="#l7">     7</a> <span class="kn">import</span> <span class="nn">itertools</span></td>
+  <td class="source followlines-btn-parent"><a href="#l7">     7</a> <span class="kn">import</span><span class="w"> </span><span class="nn">itertools</span></td> (pygments219 !)
+  <td class="source followlines-btn-parent"><a href="#l7">     7</a> <span class="kn">import</span> <span class="nn">itertools</span></td> (no-pygments219 !)
   </tr>
   <tr id="l8" class="thisrev">
   <td class="annotate parity0">
@@ -473,7 +478,8 @@ hgweb fileannotate, html
   <a href="/rev/687f2d169546">changeset</a>
   </div>
   </td>
-  <td class="source followlines-btn-parent"><a href="#l9">     9</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></td>
+  <td class="source followlines-btn-parent"><a href="#l9">     9</a> <span class="kn">def</span><span class="w"> </span><span class="nf">primes</span><span class="p">():</span></td> (pygments219 !)
+  <td class="source followlines-btn-parent"><a href="#l9">     9</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></td> (no-pygments219 !)
   </tr>
   <tr id="l10" class="thisrev">
   <td class="annotate parity0">
@@ -508,7 +514,8 @@ hgweb fileannotate, html
   <a href="/rev/687f2d169546">changeset</a>
   </div>
   </td>
-  <td class="source followlines-btn-parent"><a href="#l11">    11</a>     <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td>
+  <td class="source followlines-btn-parent"><a href="#l11">    11</a>     <span class="kn">def</span><span class="w"> </span><span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td> (pygments219 !)
+  <td class="source followlines-btn-parent"><a href="#l11">    11</a>     <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td> (no-pygments219 !)
   </tr>
   <tr id="l12" class="thisrev">
   <td class="annotate parity0">
@@ -746,7 +753,8 @@ hgweb fileannotate, html
   <a href="/rev/687f2d169546">changeset</a>
   </div>
   </td>
-  <td class="source followlines-btn-parent"><a href="#l25">    25</a>     <span class="kn">import</span> <span class="nn">sys</span></td>
+  <td class="source followlines-btn-parent"><a href="#l25">    25</a>     <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span></td> (pygments219 !)
+  <td class="source followlines-btn-parent"><a href="#l25">    25</a>     <span class="kn">import</span> <span class="nn">sys</span></td> (no-pygments219 !)
   </tr>
   <tr id="l26" class="thisrev">
   <td class="annotate parity0">
@@ -1022,7 +1030,8 @@ We attempt to highlight unknown files by default
   $ cat hg.pid >> $DAEMON_PIDS
 
   $ get-with-headers.py localhost:$HGPORT 'file/tip/unknownfile' | grep l2
-  <span id="l2"><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span></span><a href="#l2"></a>
+  <span id="l2"><span class="k">def</span><span class="w"> </span><span class="nf">foo</span><span class="p">():</span></span><a href="#l2"></a> (pygments219 !)
+  <span id="l2"><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span></span><a href="#l2"></a> (no-pygments219 !)
 
 We can prevent Pygments from falling back to a non filename-based
 detection mode
diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t
index 30564a20346646d3e9159a5b55a30eff317c4276..f87c9529a34b3c0064fee0dad04e8a1af36c8ff5 100644
--- a/tests/test-persistent-nodemap.t
+++ b/tests/test-persistent-nodemap.t
@@ -945,9 +945,11 @@ Persistent nodemap and local/streaming clone
 standard clone
 --------------
 
-The persistent nodemap should exist after a streaming clone
+The persistent nodemap should exist after a normal clone
 
   $ hg clone --pull --quiet -U test-repo standard-clone
+  $ hg debugformat -R standard-clone | grep persistent-nodemap
+  persistent-nodemap: yes
   $ ls -1 standard-clone/.hg/store/ | grep -E '00(changelog|manifest)(\.n|-.*\.nd)'
   00changelog-*.nd (glob)
   00changelog.n
@@ -961,6 +963,19 @@ The persistent nodemap should exist after a streaming clone
   data-unused: 0
   data-unused: 0.000%
 
+standard clone, no nodemap requested
+-------------------------------------
+
+If persistent normal is requested to not be here, it should not exist after a normal clone
+
+  $ hg clone --pull --quiet -U test-repo standard-clone-no-nm \
+  >     --config format.use-persistent-nodemap=no
+  $ hg debugformat -R standard-clone-no-nm | grep persistent-nodemap
+  persistent-nodemap:  no
+  $ ls -1 standard-clone-no-nm/.hg/store/ | grep -E '00(changelog|manifest)(\.n|-.*\.nd)'
+  [1]
+  $ hg -R standard-clone-no-nm debugnodemap --metadata
+
 
 local clone
 ------------
@@ -968,6 +983,8 @@ local clone
 The persistent nodemap should exist after a streaming clone
 
   $ hg clone -U test-repo local-clone
+  $ hg debugformat -R local-clone | grep persistent-nodemap
+  persistent-nodemap: yes
   $ ls -1 local-clone/.hg/store/ | grep -E '00(changelog|manifest)(\.n|-.*\.nd)'
   00changelog-*.nd (glob)
   00changelog.n
@@ -981,6 +998,44 @@ The persistent nodemap should exist after a streaming clone
   data-unused: 0
   data-unused: 0.000%
 
+stream clone
+------------
+
+  $ hg clone -U  --stream ssh://user@dummy/test-repo stream-clone --quiet
+  $ hg debugformat -R stream-clone | grep persistent-nodemap
+  persistent-nodemap: yes
+  $ ls -1 stream-clone/.hg/store/ | grep -E '00(changelog|manifest)(\.n|-.*\.nd)'
+  00changelog-*.nd (glob)
+  00changelog.n
+  00manifest-*.nd (glob)
+  00manifest.n
+  $ hg -R stream-clone debugnodemap --metadata
+  uid: * (glob)
+  tip-rev: 5005
+  tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
+  data-length: 121088
+  data-unused: 0
+  data-unused: 0.000%
+
+stream requesting no persistent nodemap
+---------------------------------------
+
+Even if persistent nodemap affect the store, there is logic to stream clone
+without it.
+
+This helps client without supports for persistent nodemap.
+
+  $ hg clone -U --stream ssh://user@dummy/test-repo stream-clone-no-nm \
+  >     --config format.use-persistent-nodemap=no \
+  >     --config devel.persistent-nodemap=no \
+  >     --config revlog.persistent-nodemap.slow-path=no \
+  >     --quiet
+  $ hg debugformat -R stream-clone-no-nm | grep persistent-nodemap
+  persistent-nodemap:  no
+  $ ls -1 stream-clone-no-nm/.hg/store/ | grep -E '00(changelog|manifest)(\.n|-.*\.nd)'
+  [1]
+  $ hg -R stream-clone-no-nm debugnodemap --metadata
+
 Test various corruption case
 ============================
 
diff --git a/tests/test-stream-bundle-v2.t b/tests/test-stream-bundle-v2.t
index 87e00957e72f687a08308e392619f3c72af22f49..a2666de254055c497231d8a458927f198b9c74c0 100644
--- a/tests/test-stream-bundle-v2.t
+++ b/tests/test-stream-bundle-v2.t
@@ -36,6 +36,8 @@ Test creating a consuming stream bundle v2 and v3
   $ cp $HGRCPATH $TESTTMP/hgrc.orig
 
   $ cat >> $HGRCPATH << EOF
+  > [ui]
+  > portablefilenames=abort
   > [experimental]
   > evolution.createmarkers=True
   > evolution.exchange=True
@@ -60,11 +62,11 @@ The extension requires a repo (currently unused)
   $ hg debugdrawdag <<'EOF'
   > E
   > |
-  > D
+  > D  # D/ba"r=<deleted>
   > |
-  > C
+  > C  # C/ba"r=faz
   > |
-  > B
+  > B  # B/blu=fuz
   > |
   > A
   > EOF
@@ -72,9 +74,9 @@ The extension requires a repo (currently unused)
   $ hg bundle -a --type="none-v2;stream=$stream_version" bundle.hg
   $ hg debugbundle bundle.hg
   Stream params: {}
-  stream2 -- {bytecount: 1693, filecount: 12, requirements: generaldelta%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 no-zstd !)
-  stream2 -- {bytecount: 1693, filecount: 12, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 zstd no-rust !)
-  stream2 -- {bytecount: 1819, filecount: 14, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 rust !)
+  stream2 -- {bytecount: 1908, filecount: 14, requirements: generaldelta%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 no-zstd !)
+  stream2 -- {bytecount: 1911, filecount: 14, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 zstd no-rust !)
+  stream2 -- {bytecount: 2103, filecount: 16, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 rust !)
   stream3-exp -- {requirements: generaldelta%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v3 no-zstd !)
   stream3-exp -- {requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v3 zstd no-rust !)
   stream3-exp -- {requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v3 rust !)
@@ -89,9 +91,9 @@ The extension requires a repo (currently unused)
   $ hg bundle -a --type="none-$bundle_format" bundle.hg
   $ hg debugbundle bundle.hg
   Stream params: {}
-  stream2 -- {bytecount: 1693, filecount: 12, requirements: generaldelta%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 no-zstd !)
-  stream2 -- {bytecount: 1693, filecount: 12, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 zstd no-rust !)
-  stream2 -- {bytecount: 1819, filecount: 14, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 rust !)
+  stream2 -- {bytecount: 1908, filecount: 14, requirements: generaldelta%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 no-zstd !)
+  stream2 -- {bytecount: 1911, filecount: 14, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 zstd no-rust !)
+  stream2 -- {bytecount: 2103, filecount: 16, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v2 rust !)
   stream3-exp -- {requirements: generaldelta%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v3 no-zstd !)
   stream3-exp -- {requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v3 zstd no-rust !)
   stream3-exp -- {requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (stream-v3 rust !)
@@ -109,20 +111,22 @@ The extension requires a repo (currently unused)
   $ "$PYTHON" $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
   $ cat http.pid >> $DAEMON_PIDS
 
+  $ cd ..
+
+
+Requirements filtering
+======================
+
+
+Unknown requirements
+--------------------
+
 Stream bundle spec with unknown requirements should be filtered out
 
-#if stream-v2
-  $ cat > .hg/clonebundles.manifest << EOF
-  > http://localhost:$HGPORT1/bundle.hg BUNDLESPEC=none-v2;stream=v2;requirements%3Drevlogv42
-  > EOF
-#endif
-#if stream-v3
-  $ cat > .hg/clonebundles.manifest << EOF
-  > http://localhost:$HGPORT1/bundle.hg BUNDLESPEC=none-v2;stream=v3-exp;requirements%3Drevlogv42
+  $ cat > main/.hg/clonebundles.manifest << EOF
+  > http://localhost:$HGPORT1/bundle.hg BUNDLESPEC=none-v2;stream=$stream_version;requirements%3Drevlogv42
   > EOF
-#endif
 
-  $ cd ..
 
   $ hg clone -U http://localhost:$HGPORT stream-clone-unsupported-requirements
   no compatible clone bundles available on server; falling back to regular clone
@@ -131,10 +135,51 @@ Stream bundle spec with unknown requirements should be filtered out
   adding changesets
   adding manifests
   adding file changes
-  added 5 changesets with 5 changes to 5 files
-  new changesets 426bada5c675:9bc730a19041 (5 drafts)
+  added 5 changesets with 7 changes to 7 files
+  new changesets 426bada5c675:92165ab525bf (5 drafts)
+
+known requirements
+------------------
+
+Stream bundle spec with known requirements should be filtered out
+
+
+
+  $ cat > main/.hg/clonebundles.manifest << EOF
+  > http://localhost:$HGPORT1/bundle.hg BUNDLESPEC=none-v2;stream=$stream_version;requirements%3Dsparserevlog,revlogv1
+  > EOF
+
+  $ hg clone -U http://localhost:$HGPORT stream-clone-supported-requirements
+  applying clone bundle from http://localhost:$HGPORT1/bundle.hg
+  * to transfer* (glob)
+  stream-cloned * in * seconds (*/sec) (glob)
+  finished applying clone bundle
+  searching for changes
+  no changes found
+
+
+known but irrelevant requirements
+---------------------------------
+
+As fncache and dotencode are abstracted by the vfs, they don't actually matters for streamclone
+
+  $ cat > main/.hg/clonebundles.manifest << EOF
+  > http://localhost:$HGPORT1/bundle.hg BUNDLESPEC=none-v2;stream=$stream_version;requirements%3Dshare-safe
+  > http://localhost:$HGPORT1/bundle.hg BUNDLESPEC=none-v2;stream=$stream_version;requirements%3Dshare-safe,fncache,dotencode
+  > EOF
+
+  $ hg clone -U http://localhost:$HGPORT stream-clone-ignorable-requirements
+  applying clone bundle from http://localhost:$HGPORT1/bundle.hg
+  * to transfer* (glob)
+  stream-cloned * in * seconds (*/sec) (glob)
+  finished applying clone bundle
+  searching for changes
+  no changes found
+
+
 
 Test that we can apply the bundle as a stream clone bundle
+==========================================================
 
   $ cat > main/.hg/clonebundles.manifest << EOF
   > http://localhost:$HGPORT1/bundle.hg BUNDLESPEC=`hg debugbundle --spec main/bundle.hg`
@@ -150,8 +195,9 @@ Test that we can apply the bundle as a stream clone bundle
   bundle2-input-bundle: with-transaction
   bundle2-input-part: "stream2" (params: 3 mandatory) supported
   applying stream bundle
-  12 files to transfer, 1.65 KB of data (no-rust !)
-  14 files to transfer, 1.78 KB of data (rust !)
+  14 files to transfer, 1.86 KB of data (no-rust no-zstd !)
+  14 files to transfer, 1.87 KB of data (no-rust zstd !)
+  16 files to transfer, 2.05 KB of data (rust !)
   starting 4 threads for background file closing (?)
   starting 4 threads for background file closing (?)
   adding [s] data/A.i (66 bytes)
@@ -159,19 +205,25 @@ Test that we can apply the bundle as a stream clone bundle
   adding [s] data/C.i (66 bytes)
   adding [s] data/D.i (66 bytes)
   adding [s] data/E.i (66 bytes)
+  adding [s] data/ba"r.i (68 bytes)
+  adding [s] data/blu.i (68 bytes)
   adding [s] phaseroots (43 bytes)
-  adding [s] 00manifest.i (584 bytes)
+  adding [s] 00manifest.i (649 bytes) (no-zstd !)
+  adding [s] 00manifest.i (652 bytes) (zstd no-rust !)
+  adding [s] 00manifest.i (654 bytes) (zstd rust !)
   adding [s] 00changelog.n (62 bytes) (rust !)
-  adding [s] 00changelog-b875dfc5.nd (64 bytes) (rust !)
-  adding [s] 00changelog.d (275 bytes)
+  adding [s] 00changelog-b875dfc5.nd (128 bytes) (rust !)
+  adding [s] 00changelog.d (289 bytes)
   adding [s] 00changelog.i (320 bytes)
   adding [c] branch2-served (94 bytes)
   adding [c] rbc-names-v2 (7 bytes)
   adding [c] rbc-revs-v2 (40 bytes)
-  bundle2-input-part: total payload size 1857 (no-rust !)
-  bundle2-input-part: total payload size 2025 (rust !)
-  stream-cloned 12 files / 1.65 KB in * seconds (* */sec) (glob) (no-rust !)
-  stream-cloned 14 files / 1.78 KB in * seconds (* */sec) (glob) (rust !)
+  bundle2-input-part: total payload size 2099 (no-rust no-zstd !)
+  bundle2-input-part: total payload size 2102 (no-rust zstd !)
+  bundle2-input-part: total payload size 2337 (rust !)
+  stream-cloned 14 files / 1.86 KB in * seconds (* */sec) (glob) (no-rust no-zstd !)
+  stream-cloned 14 files / 1.87 KB in * seconds (* */sec) (glob) (no-rust zstd !)
+  stream-cloned 16 files / 2.05 KB in * seconds (* */sec) (glob) (rust !)
   bundle2-input-bundle: 1 parts total
   updating the branch cache
   finished applying clone bundle
@@ -190,7 +242,7 @@ Test that we can apply the bundle as a stream clone bundle
   updating to branch default
   resolving manifests (no-rust !)
    branchmerge: False, force: False, partial: False (no-rust !)
-   ancestor: 000000000000, local: 000000000000+, remote: 9bc730a19041 (no-rust !)
+   ancestor: 000000000000, local: 000000000000+, remote: 92165ab525bf (no-rust !)
    A: remote created -> g (no-rust !)
   getting A (no-rust !)
    B: remote created -> g (no-rust !)
@@ -201,7 +253,9 @@ Test that we can apply the bundle as a stream clone bundle
   getting D (no-rust !)
    E: remote created -> g (no-rust !)
   getting E (no-rust !)
-  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+   blu: remote created -> g (no-rust !)
+  getting blu (no-rust !)
+  6 files updated, 0 files merged, 0 files removed, 0 files unresolved
   updating the branch cache
   (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
 
@@ -218,8 +272,9 @@ test explicite stream request
   bundle2-input-bundle: with-transaction
   bundle2-input-part: "stream2" (params: 3 mandatory) supported
   applying stream bundle
-  12 files to transfer, 1.65 KB of data (no-rust !)
-  14 files to transfer, 1.78 KB of data (rust !)
+  14 files to transfer, 1.86 KB of data (no-rust no-zstd !)
+  14 files to transfer, 1.87 KB of data (no-rust zstd !)
+  16 files to transfer, 2.05 KB of data (rust !)
   starting 4 threads for background file closing (?)
   starting 4 threads for background file closing (?)
   adding [s] data/A.i (66 bytes)
@@ -227,19 +282,25 @@ test explicite stream request
   adding [s] data/C.i (66 bytes)
   adding [s] data/D.i (66 bytes)
   adding [s] data/E.i (66 bytes)
+  adding [s] data/ba"r.i (68 bytes)
+  adding [s] data/blu.i (68 bytes)
   adding [s] phaseroots (43 bytes)
-  adding [s] 00manifest.i (584 bytes)
+  adding [s] 00manifest.i (649 bytes) (no-zstd !)
+  adding [s] 00manifest.i (652 bytes) (zstd no-rust !)
+  adding [s] 00manifest.i (654 bytes) (zstd rust !)
   adding [s] 00changelog.n (62 bytes) (rust !)
-  adding [s] 00changelog-b875dfc5.nd (64 bytes) (rust !)
-  adding [s] 00changelog.d (275 bytes)
+  adding [s] 00changelog-b875dfc5.nd (128 bytes) (rust !)
+  adding [s] 00changelog.d (289 bytes)
   adding [s] 00changelog.i (320 bytes)
   adding [c] branch2-served (94 bytes)
   adding [c] rbc-names-v2 (7 bytes)
   adding [c] rbc-revs-v2 (40 bytes)
-  bundle2-input-part: total payload size 1857 (no-rust !)
-  bundle2-input-part: total payload size 2025 (rust !)
-  stream-cloned 12 files / 1.65 KB in * seconds (* */sec) (glob) (no-rust !)
-  stream-cloned 14 files / 1.78 KB in * seconds (* */sec) (glob) (rust !)
+  bundle2-input-part: total payload size 2099 (no-rust no-zstd !)
+  bundle2-input-part: total payload size 2102 (no-rust zstd !)
+  bundle2-input-part: total payload size 2337 (rust !)
+  stream-cloned 14 files / 1.86 KB in * seconds (* */sec) (glob) (no-rust no-zstd !)
+  stream-cloned 14 files / 1.87 KB in * seconds (* */sec) (glob) (no-rust zstd !)
+  stream-cloned 16 files / 2.05 KB in * seconds (* */sec) (glob) (rust !)
   bundle2-input-bundle: 1 parts total
   updating the branch cache
   finished applying clone bundle
@@ -258,7 +319,7 @@ test explicite stream request
   updating to branch default
   resolving manifests (no-rust !)
    branchmerge: False, force: False, partial: False (no-rust !)
-   ancestor: 000000000000, local: 000000000000+, remote: 9bc730a19041 (no-rust !)
+   ancestor: 000000000000, local: 000000000000+, remote: 92165ab525bf (no-rust !)
    A: remote created -> g (no-rust !)
   getting A (no-rust !)
    B: remote created -> g (no-rust !)
@@ -269,7 +330,9 @@ test explicite stream request
   getting D (no-rust !)
    E: remote created -> g (no-rust !)
   getting E (no-rust !)
-  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+   blu: remote created -> g (no-rust !)
+  getting blu (no-rust !)
+  6 files updated, 0 files merged, 0 files removed, 0 files unresolved
   updating the branch cache
   (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
 
@@ -284,7 +347,7 @@ test explicite stream request
   bundle2-input-bundle: with-transaction
   bundle2-input-part: "stream3-exp" (params: 1 mandatory) supported
   applying stream bundle
-  11 entries to transfer
+  13 entries to transfer
   starting 4 threads for background file closing (?)
   starting 4 threads for background file closing (?)
   adding [s] data/A.i (66 bytes)
@@ -292,19 +355,25 @@ test explicite stream request
   adding [s] data/C.i (66 bytes)
   adding [s] data/D.i (66 bytes)
   adding [s] data/E.i (66 bytes)
+  adding [s] data/ba"r.i (68 bytes)
+  adding [s] data/blu.i (68 bytes)
   adding [s] phaseroots (43 bytes)
-  adding [s] 00manifest.i (584 bytes)
+  adding [s] 00manifest.i (649 bytes) (no-zstd !)
+  adding [s] 00manifest.i (652 bytes) (zstd no-rust !)
+  adding [s] 00manifest.i (654 bytes) (zstd rust !)
   adding [s] 00changelog.n (62 bytes) (rust !)
-  adding [s] 00changelog-b875dfc5.nd (64 bytes) (rust !)
-  adding [s] 00changelog.d (275 bytes)
+  adding [s] 00changelog-b875dfc5.nd (128 bytes) (rust !)
+  adding [s] 00changelog.d (289 bytes)
   adding [s] 00changelog.i (320 bytes)
   adding [c] branch2-served (94 bytes)
   adding [c] rbc-names-v2 (7 bytes)
   adding [c] rbc-revs-v2 (40 bytes)
-  stream-cloned 12 files / 1.65 KB in * seconds (* */sec) (glob) (no-rust !)
-  bundle2-input-part: total payload size 1869 (no-rust !)
-  stream-cloned 14 files / 1.78 KB in * seconds (* */sec) (glob) (rust !)
-  bundle2-input-part: total payload size 2037 (rust !)
+  stream-cloned 14 files / 1.86 KB in * seconds (* */sec) (glob) (no-rust no-zstd !)
+  stream-cloned 14 files / 1.87 KB in * seconds (* */sec) (glob) (no-rust zstd !)
+  bundle2-input-part: total payload size 2113 (no-rust no-zstd !)
+  bundle2-input-part: total payload size 2116 (no-rust zstd !)
+  stream-cloned 16 files / 2.05 KB in * seconds (* */sec) (glob) (rust !)
+  bundle2-input-part: total payload size 2351 (rust !)
   bundle2-input-bundle: 1 parts total
   updating the branch cache
   finished applying clone bundle
@@ -323,7 +392,7 @@ test explicite stream request
   updating to branch default
   resolving manifests (no-rust !)
    branchmerge: False, force: False, partial: False (no-rust !)
-   ancestor: 000000000000, local: 000000000000+, remote: 9bc730a19041 (no-rust !)
+   ancestor: 000000000000, local: 000000000000+, remote: 92165ab525bf (no-rust !)
    A: remote created -> g (no-rust !)
   getting A (no-rust !)
    B: remote created -> g (no-rust !)
@@ -334,7 +403,9 @@ test explicite stream request
   getting D (no-rust !)
    E: remote created -> g (no-rust !)
   getting E (no-rust !)
-  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+   blu: remote created -> g (no-rust !)
+  getting blu (no-rust !)
+  6 files updated, 0 files merged, 0 files removed, 0 files unresolved
   updating the branch cache
   (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
 
@@ -346,7 +417,7 @@ test explicite stream request
   bundle2-input-bundle: with-transaction
   bundle2-input-part: "stream3-exp" (params: 1 mandatory) supported
   applying stream bundle
-  11 entries to transfer
+  13 entries to transfer
   starting 4 threads for background file closing (?)
   starting 4 threads for background file closing (?)
   adding [s] data/A.i (66 bytes)
@@ -354,19 +425,25 @@ test explicite stream request
   adding [s] data/C.i (66 bytes)
   adding [s] data/D.i (66 bytes)
   adding [s] data/E.i (66 bytes)
+  adding [s] data/ba"r.i (68 bytes)
+  adding [s] data/blu.i (68 bytes)
   adding [s] phaseroots (43 bytes)
-  adding [s] 00manifest.i (584 bytes)
+  adding [s] 00manifest.i (649 bytes) (no-zstd !)
+  adding [s] 00manifest.i (652 bytes) (zstd no-rust !)
+  adding [s] 00manifest.i (654 bytes) (zstd rust !)
   adding [s] 00changelog.n (62 bytes) (rust !)
-  adding [s] 00changelog-b875dfc5.nd (64 bytes) (rust !)
-  adding [s] 00changelog.d (275 bytes)
+  adding [s] 00changelog-b875dfc5.nd (128 bytes) (rust !)
+  adding [s] 00changelog.d (289 bytes)
   adding [s] 00changelog.i (320 bytes)
   adding [c] branch2-served (94 bytes)
   adding [c] rbc-names-v2 (7 bytes)
   adding [c] rbc-revs-v2 (40 bytes)
-  stream-cloned 12 files / 1.65 KB in * seconds (* */sec) (glob) (no-rust !)
-  bundle2-input-part: total payload size 1869 (no-rust !)
-  stream-cloned 14 files / 1.78 KB in * seconds (* */sec) (glob) (rust !)
-  bundle2-input-part: total payload size 2037 (rust !)
+  stream-cloned 14 files / 1.86 KB in * seconds (* */sec) (glob) (no-rust no-zstd !)
+  stream-cloned 14 files / 1.87 KB in * seconds (* */sec) (glob) (no-rust zstd !)
+  bundle2-input-part: total payload size 2113 (no-rust no-zstd !)
+  bundle2-input-part: total payload size 2116 (no-rust zstd !)
+  stream-cloned 16 files / 2.05 KB in * seconds (* */sec) (glob) (rust !)
+  bundle2-input-part: total payload size 2351 (rust !)
   bundle2-input-bundle: 1 parts total
   updating the branch cache
   finished applying clone bundle
@@ -385,7 +462,7 @@ test explicite stream request
   updating to branch default
   resolving manifests (no-rust !)
    branchmerge: False, force: False, partial: False (no-rust !)
-   ancestor: 000000000000, local: 000000000000+, remote: 9bc730a19041 (no-rust !)
+   ancestor: 000000000000, local: 000000000000+, remote: 92165ab525bf (no-rust !)
    A: remote created -> g (no-rust !)
   getting A (no-rust !)
    B: remote created -> g (no-rust !)
@@ -396,7 +473,9 @@ test explicite stream request
   getting D (no-rust !)
    E: remote created -> g (no-rust !)
   getting E (no-rust !)
-  5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+   blu: remote created -> g (no-rust !)
+  getting blu (no-rust !)
+  6 files updated, 0 files merged, 0 files removed, 0 files unresolved
   updating the branch cache
   (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)