changeset 11627:04f76a954842

protocol: move the streamclone implementation into wireproto
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Tue, 20 Jul 2010 20:52:23 +0200
parents 2f8adc60e013
children 0c23085f051f
files mercurial/streamclone.py mercurial/wireproto.py
diffstat 2 files changed, 47 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/streamclone.py	Tue Jul 20 09:56:37 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-# streamclone.py - streaming clone server support for mercurial
-#
-# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2 or any later version.
-
-import util, error
-from mercurial import store
-
-# if server supports streaming clone, it advertises "stream"
-# capability with value that is version+flags of repo it is serving.
-# client only streams if it can read that repo format.
-
-# stream file format is simple.
-#
-# server writes out line that says how many files, how many total
-# bytes.  separator is ascii space, byte counts are strings.
-#
-# then for each file:
-#
-#   server writes out line that says filename, how many bytes in
-#   file.  separator is ascii nul, byte count is string.
-#
-#   server writes out raw file data.
-
-def allowed(ui):
-    return ui.configbool('server', 'uncompressed', True, untrusted=True)
-
-def stream_out(repo):
-    '''stream out all metadata files in repository.
-    writes to file-like object, must support write() and optional flush().'''
-
-    if not allowed(repo.ui):
-        yield '1\n' # error: 1
-        return
-
-    entries = []
-    total_bytes = 0
-    try:
-        # get consistent snapshot of repo, lock during scan
-        lock = repo.lock()
-        try:
-            repo.ui.debug('scanning\n')
-            for name, ename, size in repo.store.walk():
-                entries.append((name, size))
-                total_bytes += size
-        finally:
-            lock.release()
-    except error.LockError:
-        yield '2\n' # error: 2
-        return
-
-    yield '0\n' # success
-    repo.ui.debug('%d files, %d bytes to transfer\n' %
-                  (len(entries), total_bytes))
-    yield '%d %d\n' % (len(entries), total_bytes)
-    for name, size in entries:
-        repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
-        # partially encode name over the wire for backwards compat
-        yield '%s\0%d\n' % (store.encodedir(name), size)
-        for chunk in util.filechunkiter(repo.sopener(name), limit=size):
-            yield chunk
--- a/mercurial/wireproto.py	Tue Jul 20 09:56:37 2010 +0200
+++ b/mercurial/wireproto.py	Tue Jul 20 20:52:23 2010 +0200
@@ -9,7 +9,7 @@
 from i18n import _
 from node import bin, hex
 import changegroup as changegroupmod
-import streamclone, repo, error, encoding, util
+import repo, error, encoding, util, store
 import pushkey as pushkey_
 
 # list of nodes encoding / decoding
@@ -171,7 +171,7 @@
 
 def capabilities(repo, proto):
     caps = 'lookup changegroupsubset branchmap pushkey'.split()
-    if streamclone.allowed(repo.ui):
+    if _allowstream(repo.ui):
         caps.append('stream=%d' % repo.changelog.version)
     caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
     return ' '.join(caps)
@@ -220,8 +220,52 @@
     r = pushkey_.push(repo, namespace, key, old, new)
     return '%s\n' % int(r)
 
+def _allowstream(ui):
+    return ui.configbool('server', 'uncompressed', True, untrusted=True)
+
 def stream(repo, proto):
-    return streamres(streamclone.stream_out(repo))
+    '''If the server supports streaming clone, it advertises the "stream"
+    capability with a value representing the version and flags of the repo
+    it is serving. Client checks to see if it understands the format.
+
+    The format is simple: the server writes out a line with the amount
+    of files, then the total amount of bytes to be transfered (separated
+    by a space). Then, for each file, the server first writes the filename
+    and filesize (separated by the null character), then the file contents.
+    '''
+
+    if not _allowstream(repo.ui):
+        return '1\n'
+
+    entries = []
+    total_bytes = 0
+    try:
+        # get consistent snapshot of repo, lock during scan
+        lock = repo.lock()
+        try:
+            repo.ui.debug('scanning\n')
+            for name, ename, size in repo.store.walk():
+                entries.append((name, size))
+                total_bytes += size
+        finally:
+            lock.release()
+    except error.LockError:
+        return '2\n' # error: 2
+
+    def streamer(repo, entries, total):
+        '''stream out all metadata files in repository.'''
+        yield '0\n' # success
+        repo.ui.debug('%d files, %d bytes to transfer\n' %
+                      (len(entries), total_bytes))
+        yield '%d %d\n' % (len(entries), total_bytes)
+        for name, size in entries:
+            repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
+            # partially encode name over the wire for backwards compat
+            yield '%s\0%d\n' % (store.encodedir(name), size)
+            for chunk in util.filechunkiter(repo.sopener(name), limit=size):
+                yield chunk
+
+    return streamres(streamer(repo, entries, total_bytes))
 
 def unbundle(repo, proto, heads):
     their_heads = decodelist(heads)