Skip to content

Commit 51d34f0

Browse files
author
Leo Ji
committed
dedup: compute new filelist atomically before swapping in
Made-with: Cursor
1 parent b155426 commit 51d34f0

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

src/zarr/storage/_zip.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ def _dedup_central_directory(self) -> None:
134134
many zip readers and wastes space. Before closing, we keep only the
135135
*last* (most recent) entry for every filename so that the on-disk central
136136
directory is clean.
137+
138+
Both ``filelist`` and ``NameToInfo`` are computed upfront and then
139+
swapped in together so that the ZipFile object is never left in an
140+
inconsistent state if an exception occurs mid-update.
137141
"""
138142
if self._zf.mode not in ("w", "a", "x"):
139143
return
@@ -143,8 +147,12 @@ def _dedup_central_directory(self) -> None:
143147
if info.filename not in seen:
144148
seen.add(info.filename)
145149
deduped.append(info)
146-
self._zf.filelist = list(reversed(deduped))
147-
self._zf.NameToInfo = {info.filename: info for info in self._zf.filelist}
150+
new_filelist = list(reversed(deduped))
151+
new_name_to_info = {info.filename: info for info in new_filelist}
152+
# Swap both attributes together; if anything above raised, the
153+
# original filelist/NameToInfo are still intact.
154+
self._zf.filelist = new_filelist
155+
self._zf.NameToInfo = new_name_to_info
148156

149157
async def clear(self) -> None:
150158
# docstring inherited

0 commit comments

Comments
 (0)