Skip to content

Commit

Permalink
hdiffpatch compression and header.
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Feb 1, 2020
1 parent 15a219c commit a1cc2c2
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 40 deletions.
6 changes: 4 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ differences:
- AArch64

There is also a wrapper of `HDiffPatch`_, implementing basic
operations.
operations. Adds a custom header, so it is not compatible with
original HDiffPatch implementation as of today.

Project homepage: https://github.com/eerimoq/detools

Expand Down Expand Up @@ -135,7 +136,8 @@ the original HDiffPatch program.
$ ls -l foo-hdiffpatch.patch
-rw-rw-r-- 1 erik erik 261 Apr 22 18:20 foo-hdiffpatch.patch
Lower hdiffpatch memory usage with --match-block-size.
Lower hdiffpatch memory usage with ``--match-block-size``. Mainly
useful for big files.

.. code-block:: text
Expand Down
42 changes: 39 additions & 3 deletions detools/apply.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .common import COMPRESSION_LZ4
from .common import PATCH_TYPE_NORMAL
from .common import PATCH_TYPE_IN_PLACE
from .common import PATCH_TYPE_HDIFFPATCH
from .common import format_bad_compression_string
from .common import format_bad_compression_number
from .common import file_size
Expand Down Expand Up @@ -155,14 +156,40 @@ def read_header_normal(fpatch):
patch_type, compression = unpack_header(header)

if patch_type != PATCH_TYPE_NORMAL:
raise Error("Expected patch type 0, but got {}.".format(patch_type))
raise Error(
"Expected patch type {}, but got {}.".format(PATCH_TYPE_NORMAL,
patch_type))

compression = convert_compression(compression)
to_size = unpack_size(fpatch)

return compression, to_size


def read_header_hdiffpatch(fpatch):
"""Read a hdiffpatch header.
"""

header = fpatch.read(1)

if len(header) != 1:
raise Error('Failed to read the patch header.')

patch_type, compression = unpack_header(header)

if patch_type != PATCH_TYPE_HDIFFPATCH:
raise Error(
"Expected patch type {}, but got {}.".format(PATCH_TYPE_HDIFFPATCH,
patch_type))

compression = convert_compression(compression)
to_size = unpack_size(fpatch)
patch_size = unpack_size(fpatch)

return compression, to_size, patch_size


def read_header_in_place(fpatch):
"""Read an in-place header.
Expand All @@ -176,7 +203,9 @@ def read_header_in_place(fpatch):
patch_type, compression = unpack_header(header)

if patch_type != PATCH_TYPE_IN_PLACE:
raise Error("Expected patch type 1, but got {}.".format(patch_type))
raise Error(
"Expected patch type {}, but got {}.".format(PATCH_TYPE_IN_PLACE,
patch_type))

compression = convert_compression(compression)
memory_size = unpack_size(fpatch)
Expand Down Expand Up @@ -487,7 +516,14 @@ def apply_patch_hdiffpatch(ffrom, fpatch, fto):
"""

to_data = hdiffpatch.apply_patch(file_read(ffrom), file_read(fpatch))
compression, to_size, patch_size = read_header_hdiffpatch(fpatch)

if to_size == 0:
return to_size

patch_reader = PatchReader(fpatch, compression)
to_data = hdiffpatch.apply_patch(file_read(ffrom),
patch_reader.read(patch_size))

return fto.write(to_data)

Expand Down
5 changes: 3 additions & 2 deletions detools/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
from .bsdiff import pack_size


PATCH_TYPE_NORMAL = 0
PATCH_TYPE_IN_PLACE = 1
PATCH_TYPE_NORMAL = 0
PATCH_TYPE_IN_PLACE = 1
PATCH_TYPE_HDIFFPATCH = 2

COMPRESSION_NONE = 0
COMPRESSION_LZMA = 1
Expand Down
21 changes: 18 additions & 3 deletions detools/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .compression.lz4 import Lz4Compressor
from .common import PATCH_TYPE_NORMAL
from .common import PATCH_TYPE_IN_PLACE
from .common import PATCH_TYPE_HDIFFPATCH
from .common import DATA_FORMATS
from .common import format_bad_compression_string
from .common import compression_string_to_number
Expand Down Expand Up @@ -259,11 +260,21 @@ def create_patch_bsdiff(ffrom, fto, fpatch):
fpatch.write(fextra.getvalue())


def create_patch_hdiffpatch(ffrom, fto, fpatch, match_block_size):
def create_patch_hdiffpatch(ffrom,
fto,
fpatch,
compression,
match_block_size):
patch = hdiffpatch.create_patch(file_read(ffrom),
file_read(fto),
match_block_size)
fpatch.write(patch)
compressor = create_compressor(compression)
fpatch.write(pack_header(PATCH_TYPE_HDIFFPATCH,
compression_string_to_number(compression)))
fpatch.write(pack_size(file_size(fto)))
fpatch.write(pack_size(len(patch)))
fpatch.write(compressor.compress(patch))
fpatch.write(compressor.flush())


def create_patch(ffrom,
Expand Down Expand Up @@ -348,7 +359,11 @@ def create_patch(ffrom,
elif patch_type == 'bsdiff':
create_patch_bsdiff(ffrom, fto, fpatch)
elif patch_type == 'hdiffpatch':
create_patch_hdiffpatch(ffrom, fto, fpatch, match_block_size)
create_patch_hdiffpatch(ffrom,
fto,
fpatch,
compression,
match_block_size)
else:
raise Error("Bad patch type '{}'.".format(patch_type))

Expand Down
2 changes: 1 addition & 1 deletion detools/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.34.2'
__version__ = '0.35.0'
2 changes: 1 addition & 1 deletion src/c/detools.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
#include <stdio.h>
#include <stdbool.h>

#define PBTOOLS_VERSION "0.34.2"
#define PBTOOLS_VERSION "0.35.0"

/* Error codes. */
#define DETOOLS_OK 0
Expand Down
Binary file modified tests/files/foo/hdiffpatch-match-block-size-64.patch
Binary file not shown.
Binary file added tests/files/foo/hdiffpatch-none.patch
Binary file not shown.
Binary file modified tests/files/foo/hdiffpatch.patch
Binary file not shown.
40 changes: 40 additions & 0 deletions tests/test_command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -2031,6 +2031,27 @@ def test_command_line_create_patch_foo_hdiffpatch(self):
self.assertEqual(read_file(foo_patch),
read_file('tests/files/foo/hdiffpatch.patch'))

def test_command_line_create_patch_foo_hdiffpatch_none(self):
foo_patch = 'foo.patch'
argv = [
'detools',
'create_patch',
'--type', 'hdiffpatch',
'-c', 'none',
'tests/files/foo/old',
'tests/files/foo/new',
foo_patch
]

if os.path.exists(foo_patch):
os.remove(foo_patch)

with patch('sys.argv', argv):
detools._main()

self.assertEqual(read_file(foo_patch),
read_file('tests/files/foo/hdiffpatch-none.patch'))

def test_command_line_create_patch_foo_hdiffpatch_match_block_size_64(self):
foo_patch = 'foo.patch'
argv = [
Expand Down Expand Up @@ -2072,6 +2093,25 @@ def test_command_line_apply_patch_foo_hdiffpatch(self):
self.assertEqual(read_file(foo_new),
read_file('tests/files/foo/new'))

def test_command_line_apply_patch_foo_hdiffpatch_none(self):
foo_new = 'foo.new'
argv = [
'detools',
'apply_patch_hdiffpatch',
'tests/files/foo/old',
'tests/files/foo/hdiffpatch-none.patch',
foo_new
]

if os.path.exists(foo_new):
os.remove(foo_new)

with patch('sys.argv', argv):
detools._main()

self.assertEqual(read_file(foo_new),
read_file('tests/files/foo/new'))


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion tests/test_detools.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@ def test_create_and_apply_patch_micropython_bsdiff(self):
'bsdiff.patch',
patch_type='bsdiff')

def test_create_and_apply_patch_micropython_hdiffpatch(self):
def test_create_and_apply_patch_foo_hdiffpatch(self):
self.assert_create_and_apply_patch('tests/files/foo/old',
'tests/files/foo/new',
'tests/files/foo/hdiffpatch.patch',
Expand Down
27 changes: 0 additions & 27 deletions tests/test_hdiffpatch.py

This file was deleted.

0 comments on commit a1cc2c2

Please sign in to comment.