##// END OF EJS Templates
symlinks: minimal support for symlinks in merge/update...
symlinks: minimal support for symlinks in merge/update This will get angry, confused, and sad if you try to merge a symlink with a regular file.

File last commit:

r3891:6b4127c7 default
r4007:20da40cc default
Show More
streamclone.py
95 lines | 3.1 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.
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Matt Mackall
Replace demandload with new demandimport
r3877 import 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()