Skip to content

Commit 577400a

Browse files
committed
Update data_offset
1 parent 2ea07c6 commit 577400a

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

src/zipremove/__init__.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ def repack(self, zfile, removed=None):
177177
178178
Side effects:
179179
- Modifies the ZIP file in place.
180-
- Updates zfile.start_dir to account for removed data.
180+
- Updates zfile.start_dir and zfile.data_offset to account for
181+
removed data.
181182
- Sets zfile._didModify to True.
182183
- Updates header_offset and clears _end_offset of referenced
183184
ZipInfo instances.
@@ -282,6 +283,15 @@ def repack(self, zfile, removed=None):
282283
zfile.start_dir -= entry_offset
283284
zfile._didModify = True
284285

286+
# polyfill: update _data_offset if exists
287+
if getattr(zfile, '_data_offset', None):
288+
try:
289+
offset = filelist[0].header_offset
290+
except IndexError:
291+
offset = zfile.start_dir
292+
if offset < zfile._data_offset:
293+
zfile._data_offset = offset
294+
285295
# polyfill: clear ZipInfo._end_offset if exists
286296
# (Python >= 3.8 with fix #109858)
287297
if hasattr(ZipInfo, '_end_offset'):

tests/test_zipfile.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,8 +966,8 @@ def test_repack_prepended_bytes(self):
966966
for ii in ([], [0], [0, 1], [1], [2]):
967967
with self.subTest(remove=ii):
968968
# calculate the expected results
969-
test_files = [data for j, data in enumerate(self.test_files) if j not in ii]
970969
fz = io.BytesIO()
970+
test_files = [data for j, data in enumerate(self.test_files) if j not in ii]
971971
self._prepare_zip_from_test_files(fz, test_files)
972972
fz.seek(0)
973973
with open(TESTFN, 'wb') as fh:
@@ -985,9 +985,67 @@ def test_repack_prepended_bytes(self):
985985
fh.write(b'dummy ')
986986
fh.write(fz.read())
987987
with zipfile.ZipFile(TESTFN, 'a', self.compression) as zh:
988+
if hasattr(zh, 'data_offset'):
989+
self.assertEqual(zh.data_offset, 6)
988990
for i in ii:
989991
zh.remove(self.test_files[i][0])
990992
zh.repack()
993+
if hasattr(zh, 'data_offset'):
994+
self.assertEqual(zh.data_offset, 6)
995+
996+
# check infolist
997+
self.assertEqual(
998+
[ComparableZipInfo(zi) for zi in zh.infolist()],
999+
[ComparableZipInfo(zi) for zi in expected_zinfos],
1000+
)
1001+
1002+
# check file size
1003+
self.assertEqual(os.path.getsize(TESTFN), expected_size)
1004+
1005+
# make sure the zip file is still valid
1006+
with zipfile.ZipFile(TESTFN) as zh:
1007+
self.assertIsNone(zh.testzip())
1008+
1009+
def test_repack_prepended_file_entry(self):
1010+
for ii in ([0], [0, 1], [0, 1, 2]):
1011+
with self.subTest(remove=ii):
1012+
# calculate the expected results
1013+
fz = io.BytesIO()
1014+
test_files = [data for j, data in enumerate(self.test_files) if j not in ii]
1015+
self._prepare_zip_from_test_files(fz, test_files)
1016+
fz.seek(0)
1017+
with open(TESTFN, 'wb') as fh:
1018+
fh.write(b'dummy ')
1019+
fh.write(fz.read())
1020+
with zipfile.ZipFile(TESTFN) as zh:
1021+
expected_zinfos = list(zh.infolist())
1022+
expected_size = os.path.getsize(TESTFN)
1023+
1024+
# do the removal and check the result
1025+
fz = io.BytesIO()
1026+
with zipfile.ZipFile(fz, 'w') as zh:
1027+
for j, (file, data) in enumerate(self.test_files):
1028+
if j in ii:
1029+
zh.writestr(file, data)
1030+
fz.seek(0)
1031+
prefix = fz.read()
1032+
1033+
fz = io.BytesIO()
1034+
test_files = [data for j, data in enumerate(self.test_files) if j not in ii]
1035+
self._prepare_zip_from_test_files(fz, test_files)
1036+
fz.seek(0)
1037+
1038+
with open(TESTFN, 'wb') as fh:
1039+
fh.write(b'dummy ')
1040+
fh.write(prefix)
1041+
fh.write(fz.read())
1042+
1043+
with zipfile.ZipFile(TESTFN, 'a', self.compression) as zh:
1044+
if hasattr(zh, 'data_offset'):
1045+
self.assertEqual(zh.data_offset, 6 + len(prefix))
1046+
zh.repack()
1047+
if hasattr(zh, 'data_offset'):
1048+
self.assertEqual(zh.data_offset, 6)
9911049

9921050
# check infolist
9931051
self.assertEqual(
@@ -1177,8 +1235,12 @@ def test_repack_removed_prepended_bytes(self):
11771235
fh.write(b'dummy ')
11781236
fh.write(fz.read())
11791237
with zipfile.ZipFile(TESTFN, 'a', self.compression) as zh:
1238+
if hasattr(zh, 'data_offset'):
1239+
self.assertEqual(zh.data_offset, 6)
11801240
zinfos = [zh.remove(self.test_files[i][0]) for i in ii]
11811241
zh.repack(zinfos)
1242+
if hasattr(zh, 'data_offset'):
1243+
self.assertEqual(zh.data_offset, 6)
11821244

11831245
# check infolist
11841246
self.assertEqual(

0 commit comments

Comments
 (0)