[PATCH 2 of 5 modernize-streamclone] streamclone: refactor code for deciding to stream clone

Gregory Szorc gregory.szorc at gmail.com
Sat Oct 3 00:55:54 CDT 2015


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1443849731 25200
#      Fri Oct 02 22:22:11 2015 -0700
# Node ID 3b07d689eb21b1bae0baa38fa708fd339f3521af
# Parent  78a614c3c6def09605aa17d23da8a94a931fe6cc
streamclone: refactor code for deciding to stream clone

Having this in a standalone function will eventually enable bundle2 to
share code with the bundle1 code path.

While I was here, I also added some comments to add clarity.

diff --git a/mercurial/streamclone.py b/mercurial/streamclone.py
--- a/mercurial/streamclone.py
+++ b/mercurial/streamclone.py
@@ -16,33 +16,60 @@ from . import (
     store,
     util,
 )
 
+def canperformstreamclone(repo, remote, heads, streamrequested=None):
+    """Whether it is possible to perform a streaming clone as part of pull.
+
+    Returns a tuple of (supported, requirements). ``supported`` is True if
+    streaming clone is supported and False otherwise. ``requirements`` is
+    a set of repo requirements from the remote, or ``None`` if stream clone
+    isn't supported.
+    """
+    # Streaming clone only works if all data is being requested.
+    if heads:
+        return False, None
+
+    # If we don't have a preference, let the server decide for us. This
+    # likely only comes into play in LANs.
+    if streamrequested is None:
+        # The server can advertise whether to prefer streaming clone.
+        streamrequested = remote.capable('stream-preferred')
+
+    if not streamrequested:
+        return False, None
+
+    # In order for stream clone to work, the client has to support all the
+    # requirements advertised by the server.
+    #
+    # The server advertises its requirements via the "stream" and "streamreqs"
+    # capability. "stream" (a value-less capability) is advertised if and only
+    # if the only requirement is "revlogv1." Else, the "streamreqs" capability
+    # is advertised and contains a comma-delimited list of requirements.
+    requirements = set()
+    if remote.capable('stream'):
+        requirements.add('revlogv1')
+    else:
+        streamreqs = remote.capable('streamreqs')
+        # This is weird and shouldn't happen with modern servers.
+        if not streamreqs:
+            return False, None
+
+        streamreqs = set(streamreqs.split(','))
+        # Server requires something we don't support. Bail.
+        if streamreqs - repo.supportedformats:
+            return False, None
+        requirements = streamreqs
+
+    return True, requirements
+
 def maybeperformstreamclone(repo, remote, heads, stream):
-    # now, all clients that can request uncompressed clones can
-    # read repo formats supported by all servers that can serve
-    # them.
+    supported, requirements = canperformstreamclone(repo, remote, heads,
+                                                     streamrequested=stream)
+    if not supported:
+        return
 
-    # if revlog format changes, client will have to check version
-    # and format flags on "stream" capability, and use
-    # uncompressed only if compatible.
-
-    if stream is None:
-        # if the server explicitly prefers to stream (for fast LANs)
-        stream = remote.capable('stream-preferred')
-
-    if stream and not heads:
-        # 'stream' means remote revlog format is revlogv1 only
-        if remote.capable('stream'):
-            streamin(repo, remote, set(('revlogv1',)))
-        else:
-            # otherwise, 'streamreqs' contains the remote revlog format
-            streamreqs = remote.capable('streamreqs')
-            if streamreqs:
-                streamreqs = set(streamreqs.split(','))
-                # if we support it, stream in and adjust our requirements
-                if not streamreqs - repo.supportedformats:
-                    streamin(repo, remote, streamreqs)
+    streamin(repo, remote, requirements)
 
 def allowservergeneration(ui):
     """Whether streaming clones are allowed from the server."""
     return ui.configbool('server', 'uncompressed', True, untrusted=True)


More information about the Mercurial-devel mailing list