[PATCH] patch: add support for git delta hunks
Augie Fackler
raf at durin42.com
Wed Nov 27 08:53:29 CST 2013
On Tue, Nov 26, 2013 at 12:17:55PM +0100, Nicolas Vigier wrote:
> # HG changeset patch
> # User Nicolas Vigier <boklm at mars-attacks.org>
> # Date 1385424419 -3600
> # Node ID f8cb3b94a9f68dcca3d9545b14a7ecc21e8ba156
> # Parent 1c46b18b0e1c47fa4cecf21b78c083a54ae9903f
> patch: add support for git delta hunks
>
> When creating patches modifying binary files using "git format-patch",
> git creates 'literal' and 'delta' hunks. Mercurial currently supports
> 'literal' hunks only, which makes it impossible to import patches with
> 'delta' hunks.
>
> This changeset adds support for 'delta' hunks. It is a reimplementation
> of patch-delta.c from git :
> http://git.kernel.org/cgit/git/git.git/tree/patch-delta.c
>
> diff -r 1c46b18b0e1c -r f8cb3b94a9f6 mercurial/patch.py
> --- a/mercurial/patch.py Fri Nov 22 17:26:58 2013 -0600
> +++ b/mercurial/patch.py Tue Nov 26 01:06:59 2013 +0100
> @@ -721,8 +721,9 @@
> if self.remove:
> self.backend.unlink(self.fname)
> else:
> - self.lines[:] = h.new()
> - self.offset += len(h.new())
> + l = h.new(self.lines)
> + self.lines[:] = l
> + self.offset += len(l)
> self.dirty = True
> return 0
>
> @@ -1016,9 +1017,10 @@
> return old, oldstart, new, newstart
>
> class binhunk(object):
> - 'A binary patch file. Only understands literals so far.'
> + 'A binary patch file.'
> def __init__(self, lr, fname):
> self.text = None
> + self.delta = False
> self.hunk = ['GIT binary patch\n']
> self._fname = fname
> self._read(lr)
> @@ -1026,8 +1028,63 @@
> def complete(self):
> return self.text is not None
>
> - def new(self):
> - return [self.text]
> + def new(self, lines):
> + def deltahead(binchunk):
> + i = 0
> + for c in binchunk:
> + i += 1
> + if not (ord(c) & 0x80):
> + return i
> + return i
> + def applydelta(binchunk, data):
I may be missing something, but it look slike this nested function
could be a module-level function and then be a little more readable?
> + out = ""
> + s = deltahead(binchunk)
> + binchunk = binchunk[s:]
> + s = deltahead(binchunk)
> + binchunk = binchunk[s:]
> + i = 0
> + while i < len(binchunk):
> + cmd = ord(binchunk[i])
> + i += 1
> + if (cmd & 0x80):
> + offset = 0
> + size = 0
> + if (cmd & 0x01):
> + offset = ord(binchunk[i])
> + i += 1
> + if (cmd & 0x02):
> + offset |= ord(binchunk[i]) << 8
> + i += 1
> + if (cmd & 0x04):
> + offset |= ord(binchunk[i]) << 16
> + i += 1
> + if (cmd & 0x08):
> + offset |= ord(binchunk[i]) << 24
> + i += 1
> + if (cmd & 0x10):
> + size = ord(binchunk[i])
> + i += 1
> + if (cmd & 0x20):
> + size |= ord(binchunk[i]) << 8
> + i += 1
> + if (cmd & 0x40):
> + size |= ord(binchunk[i]) << 16
> + i += 1
> + if size == 0:
> + size = 0x10000
> + offset_end = offset + size
> + out += data[offset:offset_end]
> + elif cmd != 0:
> + offset_end = i + cmd
> + out += binchunk[i:offset_end]
> + i += cmd
> + else:
> + raise PatchError(_('unexpected delta opcode 0'))
> + return out
> + if self.delta:
> + return [applydelta(self.text, ''.join(lines))]
> + else:
> + return [self.text]
>
> def _read(self, lr):
> def getline(lr, hunk):
> @@ -1035,14 +1092,19 @@
> hunk.append(l)
> return l.rstrip('\r\n')
>
> + size = 0
> while True:
> line = getline(lr, self.hunk)
> if not line:
> raise PatchError(_('could not extract "%s" binary data')
> % self._fname)
> if line.startswith('literal '):
> + size = int(line[8:].rstrip())
> break
> - size = int(line[8:].rstrip())
> + if line.startswith('delta '):
> + size = int(line[6:].rstrip())
> + self.delta = True
> + break
> dec = []
> line = getline(lr, self.hunk)
> while len(line) > 1:
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list