mirror of
https://github.com/lloeki/rsync.git
synced 2025-12-06 02:54:39 +01:00
algorithm from http://blog.liw.fi/posts/rsync-in-python/
This commit is contained in:
commit
e7f2e7e9f0
1 changed files with 48 additions and 0 deletions
48
rsync.py
Normal file
48
rsync.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
block_size = 4096
|
||||||
|
|
||||||
|
def signature(f):
|
||||||
|
while True:
|
||||||
|
block_data = f.read(block_size)
|
||||||
|
if not block_data:
|
||||||
|
break
|
||||||
|
yield (zlib.adler32(block_data), hashlib.md5(block_data).digest())
|
||||||
|
|
||||||
|
class RsyncLookupTable(object):
|
||||||
|
|
||||||
|
def __init__(self, checksums):
|
||||||
|
self.dict = {}
|
||||||
|
for block_number, c in enumerate(checksums):
|
||||||
|
weak, strong = c
|
||||||
|
if weak not in self.dict:
|
||||||
|
self.dict[weak] = dict()
|
||||||
|
self.dict[weak][strong] = block_number
|
||||||
|
|
||||||
|
def __getitem__(self, block_data):
|
||||||
|
weak = zlib.adler32(block_data)
|
||||||
|
subdict = self.dict.get(weak)
|
||||||
|
if subdict:
|
||||||
|
strong = hashlib.md5(block_data).digest()
|
||||||
|
return subdict.get(strong)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def delta(sigs, f):
|
||||||
|
table = RsyncLookupTable(sigs)
|
||||||
|
block_data = f.read(block_size)
|
||||||
|
while block_data:
|
||||||
|
block_number = table[block_data]
|
||||||
|
if block_number:
|
||||||
|
yield (block_number * block_size, len(block_data))
|
||||||
|
block_data = f.read(block_size)
|
||||||
|
else:
|
||||||
|
yield block_data[0]
|
||||||
|
block_data = block_data[1:] + f.read(1)
|
||||||
|
|
||||||
|
def patch(outputf, deltas, old_file):
|
||||||
|
for x in deltas:
|
||||||
|
if type(x) == str:
|
||||||
|
outputf.write(x)
|
||||||
|
else:
|
||||||
|
offset, length = x
|
||||||
|
old_file.seek(offset)
|
||||||
|
outputf.write(old_file.read(length))
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue