[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