##// END OF EJS Templates
Prevent type exception on concatenation if diffstat returns None....
Prevent type exception on concatenation if diffstat returns None. This will most often occur if diffstat is not installed in the target platform, though may also happen in other cases where diffstat fails to execute. Signed-off-by: Sean Dague <sean@dague.net>

File last commit:

r3891:6b4127c7 default
r4077:1305ba7d default
Show More
streamclone.py
96 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.
from demandload import demandload
from i18n import gettext as _
Thomas Arendsen Hein
Handle locking exceptions if streaming clone can't lock the repo. (Issue324)
r3687 demandload(globals(), "os 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):
ents = os.listdir(path)
ents.sort()
for e in ents:
pe = os.path.join(path, e)
st = os.lstat(pe)
if stat.S_ISDIR(st.st_mode):
if recurse:
for x in walk(pe, True):
yield x
else:
if not stat.S_ISREG(st.st_mode) or len(e) < 2:
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.
def stream_out(repo, fileobj):
'''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
Vadim Gelfer
rename stream hgrc option to compressed.
r2622 if not repo.ui.configbool('server', 'uncompressed'):
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.
Thomas Arendsen Hein
Handle locking exceptions if streaming clone can't lock the repo. (Issue324)
r3687 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
fileobj.write('0\n')
Vadim Gelfer
add support for streaming clone....
r2612 repo.ui.debug('scanning\n')
entries = []
total_bytes = 0
Benoit Boissinot
introduce localrepo.spath for the store path, sopener fixes
r3791 for name, size in walkrepo(repo.spath):
Benoit Boissinot
streamclone: remove unnecessary test, pconvert names
r3856 name = util.pconvert(repo.decodefn(name))
Vadim Gelfer
add support for streaming clone....
r2612 entries.append((name, size))
total_bytes += size
Thomas Arendsen Hein
Handle locking exceptions if streaming clone can't lock the repo. (Issue324)
r3687 repolock.release()
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()