This commit adds a parameter to the `File#extract` and `Entry#extract` methods
so that a base destination directory can be specified for extracting archives
in bulk to somewhere in the filesystem that isn't the current working
directory. This directory is `.` by default. It is combined with the entry
path - which shouldn't but could have relative directories (e.g. `..`) in it -
and tested for safety before extracting.
Resolves#540.
This also means that we no longer need to keep a copy of the original
set of `Entry`s or the central directory comment to test for changes.
For situations where a zip file has a lot of entries (e.g. #506) this
means we save a lot of memory, and a lot of time constructing the zip
file in memory.
Set it to true by default - because a new `Entry` is dirty by
definition, having not been written yet. Then make sure that an `Entry`
that is created by reading from a zip file is set as not dirty.
This was a fairly horrible method anyway, for a number of reasons. It
looked like a method that tested whether a name was a 'directory' name
or not, and it did, but it also had some side effects where it would
convert it *to* a directory name in some cases as well. Thankfully,
nothing was using it any more, and as it was private we can lose it
safely. Gone.
There is now no direct access to the set of entries in a central
directory. This makes the interface cleaner because we now, for example,
add/delete things directly to/from the central directory, rather than
to/from the entry set contained within the central directory.
It has bothered me for years that the central directory is exposed in
this way. A zip file should *have* a central directory, but it should
not *be* one.
This commit starts us down the path of properly separating the two.
This method provides a short cut to finding out how many entries are in
an archive by reading this number directly from the central directory,
and not iterating through the entire set of entries.
This greatly simplifies the creation of `Entry` objects when only a
couple of fields are not set to their defaults, while at the same time
allowing an `Entry` to be fully configured at creation time if
appropriate.
This fundamentally changes the `Entry` API and means that some
convenience methods in `OutputStream` and `File` have needed to be
refactored.
It looks like it needs to be surfaced in `add` and `get_output_stream`.
The compression level defaults to whatever the global default is unless
it is overridden on opening the Zip::File.
Also needed to reorder some of the requires in the top-level module file
now that we are using defaults in the File class.
Allow an Entry to specify a compression level and pass this down to the
underlying OutputStream infrastructure. OutputStream has been able to
specify a compression level for a while but this has, up until now, only
ever been set to the default.
This fundamentally changes the API so will need a major version bump.
StringIO objects created within File.open_buffer were not being switched into
binmode, but those passed in were. Fix this inconsistency and add a test.
Things are now more carefully set up, and if a buffer is passed in which
represents a file that already exists then this is taken into account. All
initialization is now done in File.new, rather than being split between there
and File.open_buffer.
This has also needed a bit of a re-write of Zip::File.initialize. I've tried to
bring some logic to it as a result, and have added comments to explain what is
now happening.