##// END OF EJS Templates
use repo[changeid] to get a changectx
use repo[changeid] to get a changectx

File last commit:

r6212:e75aab65 default
r6747:f6c00b17 default
Show More
streamclone.py
94 lines | 3.2 KiB | text/x-python | PythonLexer
Vadim Gelfer
add support for streaming clone....
r2612 # 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, incorporated herein by reference.
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 import os, osutil, stat, util, lock
Vadim Gelfer
add support for streaming clone....
r2612
# 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.
def walkrepo(root):
'''iterate over metadata files in repository.
walk in natural (sorted) order.
yields 2-tuples: name of .d or .i file, size of file.'''
strip_count = len(root) + len(os.sep)
def walk(path, recurse):
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 for e, kind, st in osutil.listdir(path, stat=True):
Vadim Gelfer
add support for streaming clone....
r2612 pe = os.path.join(path, e)
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 if kind == stat.S_IFDIR:
Vadim Gelfer
add support for streaming clone....
r2612 if recurse:
for x in walk(pe, True):
yield x
else:
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 if kind != stat.S_IFREG or len(e) < 2:
Vadim Gelfer
add support for streaming clone....
r2612 continue
sfx = e[-2:]
if sfx in ('.d', '.i'):
yield pe[strip_count:], st.st_size
# write file data first
for x in walk(os.path.join(root, 'data'), True):
yield x
# write manifest before changelog
meta = list(walk(root, False))
Vadim Gelfer
fix problem with uncompressed clone and python 2.3.
r2623 meta.sort()
meta.reverse()
Vadim Gelfer
add support for streaming clone....
r2612 for x in meta:
yield x
# 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 file name, how many bytes in
# file. separator is ascii nul, byte count is string.
#
# server writes out raw file data.
Edouard Gomez
Fix inconsistency for the stream_out capability in hgweb...
r4834 def stream_out(repo, fileobj, untrusted=False):
Vadim Gelfer
add support for streaming clone....
r2612 '''stream out all metadata files in repository.
writes to file-like object, must support write() and optional flush().'''
Vadim Gelfer
clone: disable stream support on server side by default....
r2621
Edouard Gomez
Fix inconsistency for the stream_out capability in hgweb...
r4834 if not repo.ui.configbool('server', 'uncompressed', untrusted=untrusted):
Vadim Gelfer
clone: disable stream support on server side by default....
r2621 fileobj.write('1\n')
return
Vadim Gelfer
add support for streaming clone....
r2612 # get consistent snapshot of repo. lock during scan so lock not
# needed while we stream, and commits can happen.
Benoit Boissinot
fix typo
r5456 repolock = None
Thomas Arendsen Hein
Handle locking exceptions if streaming clone can't lock the repo. (Issue324)
r3687 try:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
repolock = repo.lock()
except (lock.LockHeld, lock.LockUnavailable), inst:
repo.ui.warn('locking the repository failed: %s\n' % (inst,))
fileobj.write('2\n')
return
Thomas Arendsen Hein
Handle locking exceptions if streaming clone can't lock the repo. (Issue324)
r3687
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 fileobj.write('0\n')
repo.ui.debug('scanning\n')
entries = []
total_bytes = 0
for name, size in walkrepo(repo.spath):
name = repo.decodefn(util.pconvert(name))
entries.append((name, size))
total_bytes += size
finally:
del repolock
Vadim Gelfer
add support for streaming clone....
r2612
repo.ui.debug('%d files, %d bytes to transfer\n' %
(len(entries), total_bytes))
fileobj.write('%d %d\n' % (len(entries), total_bytes))
for name, size in entries:
repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
fileobj.write('%s\0%d\n' % (name, size))
Benoit Boissinot
introduce localrepo.spath for the store path, sopener fixes
r3791 for chunk in util.filechunkiter(repo.sopener(name), limit=size):
Vadim Gelfer
add support for streaming clone....
r2612 fileobj.write(chunk)
flush = getattr(fileobj, 'flush', None)
if flush: flush()