Don't silently alter zip files opened with `Zip::sort_entries`.

Fixes #329.
This commit is contained in:
Robert Haines 2021-06-30 23:18:59 +01:00
parent 322955c6b4
commit 54b7762c8f
4 changed files with 20 additions and 7 deletions

View File

@ -1,5 +1,6 @@
# 3.0.0 (Next) # 3.0.0 (Next)
- Don't silently alter zip files opened with `Zip::sort_entries`. [#329](https://github.com/rubyzip/rubyzip/issues/329)
- Use named parameters for optional arguments in the public API. - Use named parameters for optional arguments in the public API.
- Raise an error if entry names exceed 65,535 characters. [#247](https://github.com/rubyzip/rubyzip/issues/247) - Raise an error if entry names exceed 65,535 characters. [#247](https://github.com/rubyzip/rubyzip/issues/247)
- Remove the `ZipXError` v1 legacy classes. - Remove the `ZipXError` v1 legacy classes.

View File

@ -132,9 +132,9 @@ class ZipFileGenerator
end end
``` ```
### Save zip archive entries in sorted by name state ### Save zip archive entries sorted by name
To save zip archives in sorted order like below, you need to set `::Zip.sort_entries` to `true` To save zip archives with their entries sorted by name (see below), set `::Zip.sort_entries` to `true`
``` ```
Vegetable/ Vegetable/
@ -148,7 +148,7 @@ fruit/mango
fruit/orange fruit/orange
``` ```
After this, entries in the zip archive will be saved in ordered state. Opening an existing zip file with this option set will not change the order of the entries automatically. Altering the zip file - adding an entry, renaming an entry, adding or changing the archive comment, etc - will cause the ordering to be applied when closing the file.
### Default permissions of zip archives ### Default permissions of zip archives

View File

@ -35,10 +35,8 @@ module Zip
entry if @entry_set.delete(to_key(entry)) entry if @entry_set.delete(to_key(entry))
end end
def each def each(&block)
@entry_set = sorted_entries.dup.each do |_, value| entries.each(&block)
yield(value)
end
end end
def entries def entries

View File

@ -62,9 +62,15 @@ class ZipEntrySetTest < MiniTest::Test
count = 0 count = 0
@zip_entry_set.each do |entry| @zip_entry_set.each do |entry|
assert(ZIP_ENTRIES.include?(entry)) assert(ZIP_ENTRIES.include?(entry))
refute(entry.dirty)
entry.dirty = true # Check that entries can be changed in this block.
count += 1 count += 1
end end
assert_equal(ZIP_ENTRIES.size, count) assert_equal(ZIP_ENTRIES.size, count)
@zip_entry_set.each do |entry|
assert(entry.dirty)
end
end end
def test_entries def test_entries
@ -101,6 +107,14 @@ class ZipEntrySetTest < MiniTest::Test
arr << entry arr << entry
end end
assert_equal(ZIP_ENTRIES.sort, arr) assert_equal(ZIP_ENTRIES.sort, arr)
# Ensure `each` above hasn't permanently altered the ordering.
::Zip.sort_entries = false
arr = []
@zip_entry_set.each do |entry|
arr << entry
end
assert_equal(ZIP_ENTRIES, arr)
end end
def test_compound def test_compound