MCPcopy Create free account
hub / github.com/ActiveState/code / rsyncdelta

Function rsyncdelta

recipes/Python/577518_Rsync_Algorithm/recipe-577518.py:41–120  ·  view source on GitHub ↗

Generates a binary patch when supplied with the weak and strong hashes from an unpatched target and a readable stream for the up-to-date data. The blocksize must be the same as the value used to generate remotesignatures.

(datastream, remotesignatures, blocksize=4096)

Source from the content-addressed store, hash-verified

39
40
41def rsyncdelta(datastream, remotesignatures, blocksize=4096):
42 """
43 Generates a binary patch when supplied with the weak and strong
44 hashes from an unpatched target and a readable stream for the
45 up-to-date data. The blocksize must be the same as the value
46 used to generate remotesignatures.
47 """
48 remote_weak, remote_strong = remotesignatures
49
50 match = True
51 matchblock = -1
52 deltaqueue = collections.deque()
53
54 while True:
55 if match and datastream is not None:
56 # Whenever there is a match or the loop is running for the first
57 # time, populate the window using weakchecksum instead of rolling
58 # through every single byte which takes at least twice as long.
59 window = collections.deque(bytes(datastream.read(blocksize)))
60 checksum, a, b = weakchecksum(window)
61
62 try:
63 # If there are two identical weak checksums in a file, and the
64 # matching strong hash does not occur at the first match, it will
65 # be missed and the data sent over. May fix eventually, but this
66 # problem arises very rarely.
67 matchblock = remote_weak.index(checksum, matchblock + 1)
68 stronghash = hashlib.md5(bytes(window)).hexdigest()
69 matchblock = remote_strong.index(stronghash, matchblock)
70
71 match = True
72 deltaqueue.append(matchblock)
73
74 if datastream.closed:
75 break
76 continue
77
78 except ValueError:
79 # The weakchecksum did not match
80 match = False
81 try:
82 if datastream:
83 # Get the next byte and affix to the window
84 newbyte = ord(datastream.read(1))
85 window.append(newbyte)
86 except TypeError:
87 # No more data from the file; the window will slowly shrink.
88 # newbyte needs to be zero from here on to keep the checksum
89 # correct.
90 newbyte = 0
91 tailsize = datastream.tell() % blocksize
92 datastream = None
93
94 if datastream is None and len(window) <= tailsize:
95 # The likelihood that any blocks will match after this is
96 # nearly nil so call it quits.
97 deltaqueue.append(window)
98 break

Callers

nothing calls this directly

Calls 9

bytesFunction · 0.85
weakchecksumFunction · 0.85
rollingchecksumFunction · 0.85
hexdigestMethod · 0.80
readMethod · 0.45
indexMethod · 0.45
appendMethod · 0.45
tellMethod · 0.45
popleftMethod · 0.45

Tested by

no test coverage detected