Mercurial > public > mercurial-scm > hg-stable
diff mercurial/wireproto.py @ 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 | cdeb861335d5 |
children | 4e804302d30c |
line wrap: on
line diff
--- 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)