feat(write): add ZipWriter::remove_file for in-place entry deletion - #924
Open
jstorrs wants to merge 2 commits into
Open
feat(write): add ZipWriter::remove_file for in-place entry deletion#924jstorrs wants to merge 2 commits into
jstorrs wants to merge 2 commits into
Conversation
Removes an entry from the archive's directory without rewriting the archive. The entry stops appearing to readers because `finish` omits it from the central directory it writes; its local header and data are left in place as unreferenced bytes, so nothing after the removed entry is moved and the cost does not scale with the size of the archive. This is the deletion primitive requested in zip-rs#166, where rewriting was called out as too slow on mobile devices. The file does not shrink — reclaiming the space still needs a rewrite, which a caller can now defer and batch instead of paying on every removal. The operation only mutates the in-memory directory, so it cannot corrupt surviving entries: their data is untouched and their offsets are unchanged. An entry created by `shallow_copy_file` that shares data with the removed one keeps working for the same reason, and there is a test for it. `shift_remove` rather than `swap_remove`, since the central directory is written in `files` order and reordering the survivors would be a surprising side effect of a removal. A file currently being written is finished first, matching what `start_file` does. Freeing the name also makes replace-without-rewrite possible: remove, then add the same name again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #166.
Adds
ZipWriter::remove_file(name), which drops an entry from the archive'sdirectory without rewriting the archive.
finishomits it from the centraldirectory, so readers no longer see it, while its local header and data are left
in place as unreferenced bytes. Nothing after the removed entry is moved, so the
cost does not scale with the size of the archive — which is what #166 asks for
("rewriting will take way too long on mobile devices").
The file does not shrink. Reclaiming the space still needs a rewrite; the
point is that a caller can now defer and batch that instead of paying it on every
removal. The rustdoc says so and points at
merge_archiveas one way to compact.Notes:
entries keep their offsets and their bytes. An entry from
shallow_copy_filethat shares data with the removed one keeps working; there's a test.
shift_removerather thanswap_remove: the central directory is written infilesorder, and reordering the survivors would be a surprising side effect.Test included.
start_file.a rewrite. Test included.
ZipError::FileNotFound.Seven unit tests plus a doctest. Verified locally on Linux against MSRV 1.88,
stable, and nightly, with default /
--no-default-features/--all-features,plus
fmt,clippy --all-targets, anddoc --no-deps. The remaining axes ofthe CI matrix (Windows and macOS) I leave to CI.