zip_kit 6.2.2 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1136ebba851638486c9e47150a8d706c49a2bbc0074f457c794582d8ce19089
4
- data.tar.gz: 80de3edcb5bc748aaf855a7bf0b1f19439522c8efa4b97754f813fe9413bac2c
3
+ metadata.gz: dcd59b7f9d367a40895c9bac2f909f3e22ebd0a96ee737073ef5153c4d486c70
4
+ data.tar.gz: 05665ca021d401cad02f80c38d8965c2e5fef1a477317f7ee92246d1c54a21ae
5
5
  SHA512:
6
- metadata.gz: 20c5922a4178f2068a4f06388b201bd263f01c387d308c2c6297feba1c05385d601072cae0451d59a4a0b4e1ba1e354a6fa7f622ff1b58daf70947e6991b1e82
7
- data.tar.gz: c373972ec6980000b40d1808247759b44f317a7aa3795b406e02005412cf0687e0f2311e5809f011eb1fbc19e6b2b7eb2a6a8f036cafe27a2645f6476cf0c441
6
+ metadata.gz: b13d15a467565ef66ce6a21ac3891e8a26b30246d538c232aca193c3fe24a24a8f3a2d844d48eaeaeeb5ccc2f92cfcaab20e4afa1a2717b89ba27f55bb4635e4
7
+ data.tar.gz: 29aacf905b670323861812a4aece1446917ac2f94ece22b948f5d2f77a6eb7574c39598177e7c4f33cc230fd863b4f1c02eb961c5b48e4823d40854a25368101
data/.yardopts CHANGED
@@ -1 +1 @@
1
- --markup markdown
1
+ --markup markdown --no-private --protected lib/**/*.rb - LICENSE.txt IMPLEMENTATION_DETAILS.md RUBYZIP_DIFFERENCES.md CONTRIBUTING.md CODE_OF_CONDUCT.md CHANGELOG.md
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 6.3.0
2
+
3
+ * Include `RailsStreaming` automatically via a Railtie. It is not really necessary to force people to manage it manually.
4
+
1
5
  ## 6.2.2
2
6
 
3
7
  * Make sure "zlib" gets required at the top, as it is used everywhere
data/CONTRIBUTING.md CHANGED
@@ -16,7 +16,7 @@ If you are interested in contributing code and would like to learn more about th
16
16
 
17
17
  - [ruby](https://ruby-doc.org)
18
18
  - [rubyzip](https://github.com/rubyzip/rubyzip) as we like to test "our implementation against theirs"
19
- - [rspec](http://rspec.info/) and [appraisal]() https://github.com/thoughtbot/appraisal) for testing
19
+ - [rspec](http://rspec.info/) for testing
20
20
  - [zip files](https://en.wikipedia.org/wiki/Zip_(file_format))
21
21
 
22
22
  # How do I make a contribution?
@@ -78,8 +78,8 @@ you can try this:
78
78
 
79
79
  [Encoding::CP437, Encoding::ISO_8859_1, Encoding::UTF_8]
80
80
 
81
- We don't want no such thing, and sorry Windows users, you are going to need a decent unarchiver
82
- that honors the standard. Alas, alas.
81
+ While this could work, we found it to be broken in practice as the decoding of the filename
82
+ also depends on the system locale.
83
83
 
84
84
  Additionally, the tests with the unarchivers we _do_ support have shown that including the InfoZIP
85
85
  extra field does not actually help any of them recognize the file name correctly. And the use of
data/README.md CHANGED
@@ -14,8 +14,13 @@ point. Usable for creating very large ZIP archives for immediate sending out to
14
14
  large ZIP archives without memory inflation.
15
15
 
16
16
  The original gem (zip_tricks) handled all the zipping needs (millions of ZIP files generated per day),
17
- for a large file transfer service, so we are pretty confident it is widely compatible with a large number
18
- of unarchiving end-user applications and is well tested.
17
+ for WeTransfer, it is widely compatible with a large number of unarchiving end-user applications.
18
+
19
+ ## How does it work? How is it different from Rubyzip?
20
+
21
+ Check out [the implementation details](IMPLEMENTATION_DETAILS.md) on the design of the library, and
22
+ we have a separate [reference](RUBYZIP_DIFFERENCES.md) on why you might want to use ZipKit over
23
+ Rubyzip and vice versa.
19
24
 
20
25
  ## Requirements
21
26
 
@@ -23,13 +28,11 @@ Ruby 2.6+ syntax support is required, as well as a a working zlib (all available
23
28
 
24
29
  ## Diving in: send some large CSV reports from Rails
25
30
 
26
- The easiest is to include the `ZipKit::RailsStreaming` module into your
27
- controller. You will then have a `zip_kit_stream` method available which accepts a block:
31
+ The included `Railtie` will automatically include `ZipKit::RailsStreaming` into the
32
+ `ActionController::Base` class. You will then have a `zip_kit_stream` method available which accepts a block:
28
33
 
29
34
  ```ruby
30
35
  class ZipsController < ActionController::Base
31
- include ZipKit::RailsStreaming
32
-
33
36
  def download
34
37
  zip_kit_stream do |zip|
35
38
  zip.write_file('report1.csv') do |sink|
@@ -48,6 +51,8 @@ class ZipsController < ActionController::Base
48
51
  end
49
52
  ```
50
53
 
54
+ The block receives the `ZipKit::Streamer` object you can write your files through.
55
+
51
56
  The `write_file` method will use some heuristics to determine whether your output file would benefit
52
57
  from compression, and pick the appropriate storage mode for the file accordingly.
53
58
 
@@ -0,0 +1,56 @@
1
+ # Key differences between Rubyzip and ZipKit
2
+
3
+ Please bear in mind that this is written down not to disparage [Rubyzip.](https://github.com/rubyzip/rubyzip)
4
+
5
+ Rubyzip is, by all means, a very mature, fully featured library, and while ZipKit does have overlap with it in some functionality there are
6
+ differences in supported features which may be important for you when choosing.
7
+
8
+ ## What ZipKit supports and Rubyzip does not
9
+
10
+ * ZipKit outputs archives in a streaming fashion, using data descriptors.
11
+ This allows output of archives of very large size, without buffering.
12
+ Rubyzip will seek in the already written archive to overwrite the local entry after the write of every file into the output ZIP.
13
+ At the moment, it is difficult to build a streaming Rubyzip solution due to the output of extra field placeholders.
14
+ * ZipKit supports block-deflate which allows for distributed compression of files
15
+ * ZipKit reads files from the central directory, which allows for very rapid reading. Reading works well with data descriptors
16
+ and Zip64, and is economical enough to enable "remote uncapping" where pieces of a ZIP file get read over HTTP to reconstruct
17
+ the archive structure. Actual reading can then be done on a per-entry basis. Rubyzip reads entry data from local entries, which
18
+ is error prone and much less economical than using the central directory
19
+ * ZipKit deliberately _does not_ allow you to crawl directories to add to an archive, as this has been used for security exploits
20
+ in Rubyzip.
21
+ * ZipKit deliberately _does not_ allow you to extract a ZIP archive directly to the filesystem, as this has been used for security
22
+ exploits in Rubyzip.
23
+ * When writing, ZipKit applies careful buffering to speed up CRC32 calculations. Rubyzip combines CRC32 values at every write, which
24
+ can be slow if there are many small writes.
25
+ * ZipKit comes with a Rails helper and a Rack-compatible response body for facilitating streaming. Rubyzip has no Rails integration
26
+ and no Rack integration.
27
+ * ZipKit allows you to estimate the exact size of an archive ahead of time
28
+ * ZipKit has a heuristic module which picks the storage mode (stored or deflated) depending on how well your input compresses
29
+ * ZipKit requires components using autoloading, which means that your application will likely boot faster as you will almost never
30
+ need all of the features in one codebase. Rubyzip requires its components eagerly.
31
+ * ZipKit comes with exhaustive YARD documentation and `.rbi` typedefs for [Sorbet/Tapioca](https://sorbet.org/blog/2022/07/27/srb-tapioca)
32
+
33
+ ## What Rubyzip supports and ZipKit does not
34
+
35
+ * Rubyzip allows limited manipulation of existing ZIP files by overwriting the archive entries
36
+ * Rubyzip supports "classic" ZIP encryption - both for reading and writing. ZipKit has no encryption support.
37
+ * Rubyzip allows extraction into a directory, ZipKit avoids implementing this for security reasons
38
+ * Rubyzip allows archiving a directory, ZipKit avoids implementing this for security reasons
39
+ * Rubyzip supports separate atime and ctime in the `UniversalTime` extra fields. ZipKit outputs just one timestamp
40
+ * Rubyzip attempts to faithfully replicate UNIX permissions on the files being output. ZipKit does not attempt that
41
+ because it turned out that these permissions can break unarchiving of folders on macOS.
42
+
43
+ ## Where there is currently feature parity
44
+
45
+ These used to be different, but Rubyzip has made great progress in addressing.
46
+
47
+ * ZipKit automatically applies the EFS flag for Unicode filenames in the archive. This used to be optional in RubyZip
48
+ * ZipKit automatically enables Zip64 and does so only when necessary. applies the EFS flag for Unicode filenames in the archive. This used to be optional in RubyZip.
49
+ * ZipKit outputs the `UT` precise time extra field
50
+ * ZipKit used to be distributed under the MIT-Hippocratic license which is much more restrictive than the Rubyzip BSD-2-Clause. ZipKit is now MIT-licensed.
51
+
52
+ ## Code style differences
53
+
54
+ Rubyzip is written in a somewhat Java-like style, with a lot of encapsulation and data hiding. ZipKit aims to be more approachable and have "less" of everything.
55
+ Less modules, less classes, less OOP - just enough to be useful. But that is a matter of taste, and as such should not matter to you all that much
56
+ when picking one over the other. Or it might, you never know ;-)
data/Rakefile CHANGED
@@ -11,11 +11,7 @@ task :format do
11
11
  `bundle exec magic_frozen_string_literal ./lib`
12
12
  end
13
13
 
14
- YARD::Rake::YardocTask.new(:doc) do |t|
15
- # The dash has to be between the two to "divide" the source files and
16
- # miscellaneous documentation files that contain no code
17
- t.files = ["lib/**/*.rb", "-", "LICENSE.txt", "IMPLEMENTATION_DETAILS.md"]
18
- end
14
+ YARD::Rake::YardocTask.new(:doc)
19
15
  RSpec::Core::RakeTask.new(:spec)
20
16
 
21
17
  task :generate_typedefs do
@@ -3,8 +3,7 @@
3
3
  # Should be included into a Rails controller for easy ZIP output from any action.
4
4
  module ZipKit::RailsStreaming
5
5
  # Opens a {ZipKit::Streamer} and yields it to the caller. The output of the streamer
6
- # gets automatically forwarded to the Rails response stream. When the output completes,
7
- # the Rails response stream is going to be closed automatically.
6
+ # will be sent through to the HTTP response body as it gets produced.
8
7
  #
9
8
  # Note that there is an important difference in how this method works, depending whether
10
9
  # you use it in a controller which includes `ActionController::Live` vs. one that does not.
@@ -25,7 +24,7 @@ module ZipKit::RailsStreaming
25
24
  # @param use_chunked_transfer_encoding[Boolean] whether to forcibly encode output as chunked. Normally you should not need this.
26
25
  # @param output_enumerator_options[Hash] options that will be passed to the OutputEnumerator - these include
27
26
  # options for the Streamer. See {ZipKit::OutputEnumerator#initialize} for the full list of options.
28
- # @yieldparam [ZipKit::Streamer] the streamer that can be written to
27
+ # @yieldparam [ZipKit::Streamer] zip the {ZipKit::Streamer} that can be written to
29
28
  # @return [Boolean] always returns true
30
29
  def zip_kit_stream(filename: "download.zip", type: "application/zip", use_chunked_transfer_encoding: false, **output_enumerator_options, &zip_streaming_blk)
31
30
  # We want some common headers for file sending. Rails will also set
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ZipKit::Railtie < ::Rails::Railtie
4
+ initializer "zip_kit.install_extensions" do |app|
5
+ ActionController::Base.include(ZipKit::RailsStreaming)
6
+ end
7
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ZipKit
4
- VERSION = "6.2.2"
4
+ VERSION = "6.3.0"
5
5
  end
data/lib/zip_kit.rb CHANGED
@@ -24,4 +24,6 @@ module ZipKit
24
24
  autoload :WriteShovel, File.dirname(__FILE__) + "/zip_kit/write_shovel.rb"
25
25
  autoload :RackChunkedBody, File.dirname(__FILE__) + "/zip_kit/rack_chunked_body.rb"
26
26
  autoload :RackTempfileBody, File.dirname(__FILE__) + "/zip_kit/rack_tempfile_body.rb"
27
+
28
+ require_relative "zip_kit/railtie" if defined?(::Rails)
27
29
  end
data/rbi/zip_kit.rbi CHANGED
@@ -1,6 +1,9 @@
1
1
  # typed: strong
2
2
  module ZipKit
3
- VERSION = T.let("6.2.2", T.untyped)
3
+ VERSION = T.let("6.3.0", T.untyped)
4
+
5
+ class Railtie < Rails::Railtie
6
+ end
4
7
 
5
8
  # A ZIP archive contains a flat list of entries. These entries can implicitly
6
9
  # create directories when the archive is expanded. For example, an entry with
@@ -1976,8 +1979,7 @@ end, T.untyped)
1976
1979
  # Should be included into a Rails controller for easy ZIP output from any action.
1977
1980
  module RailsStreaming
1978
1981
  # Opens a {ZipKit::Streamer} and yields it to the caller. The output of the streamer
1979
- # gets automatically forwarded to the Rails response stream. When the output completes,
1980
- # the Rails response stream is going to be closed automatically.
1982
+ # will be sent through to the HTTP response body as it gets produced.
1981
1983
  #
1982
1984
  # Note that there is an important difference in how this method works, depending whether
1983
1985
  # you use it in a controller which includes `ActionController::Live` vs. one that does not.
@@ -2008,7 +2010,7 @@ end, T.untyped)
2008
2010
  type: String,
2009
2011
  use_chunked_transfer_encoding: T::Boolean,
2010
2012
  output_enumerator_options: T::Hash[T.untyped, T.untyped],
2011
- zip_streaming_blk: T.proc.params(the: ZipKit::Streamer).void
2013
+ zip_streaming_blk: T.proc.params(zip: ZipKit::Streamer).void
2012
2014
  ).returns(T::Boolean)
2013
2015
  end
2014
2016
  def zip_kit_stream(filename: "download.zip", type: "application/zip", use_chunked_transfer_encoding: false, **output_enumerator_options, &zip_streaming_blk); end
data/zip_kit.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  # zip_kit does not use any runtime dependencies (besides zlib). However, for testing
28
28
  # things quite a few things are used - and for a good reason.
29
29
 
30
- spec.add_development_dependency "rubyzip", "~> 1" # We test our output with _another_ ZIP library, which is the way to go here
30
+ spec.add_development_dependency "rubyzip", "~> 2" # We test our output with _another_ ZIP library, which is the way to go here
31
31
  spec.add_development_dependency "rack" # For tests where we spin up a server. Both for streaming out and for testing reads over HTTP
32
32
  spec.add_development_dependency "rake", "~> 12.2"
33
33
  spec.add_development_dependency "rspec", "~> 3"
@@ -40,6 +40,7 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency "standard", "1.28.5" # Very specific version of standard for 2.6 with _known_ settings
41
41
  spec.add_development_dependency "magic_frozen_string_literal"
42
42
  spec.add_development_dependency "puma"
43
+ spec.add_development_dependency "rails", "~> 5" # For testing RailsStreaming against an actual Rails controller
43
44
  spec.add_development_dependency "actionpack", "~> 5" # For testing RailsStreaming against an actual Rails controller
44
45
  spec.add_development_dependency "nokogiri", "~> 1", ">= 1.13" # Rails 5 does by mistake use an older Nokogiri otherwise
45
46
  spec.add_development_dependency "sinatra"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zip_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.2.2
4
+ version: 6.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: exe
14
14
  cert_chain: []
15
- date: 2024-03-27 00:00:00.000000000 Z
15
+ date: 2024-04-01 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bundler
@@ -34,14 +34,14 @@ dependencies:
34
34
  requirements:
35
35
  - - "~>"
36
36
  - !ruby/object:Gem::Version
37
- version: '1'
37
+ version: '2'
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  requirements:
42
42
  - - "~>"
43
43
  - !ruby/object:Gem::Version
44
- version: '1'
44
+ version: '2'
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: rack
47
47
  requirement: !ruby/object:Gem::Requirement
@@ -216,6 +216,20 @@ dependencies:
216
216
  - - ">="
217
217
  - !ruby/object:Gem::Version
218
218
  version: '0'
219
+ - !ruby/object:Gem::Dependency
220
+ name: rails
221
+ requirement: !ruby/object:Gem::Requirement
222
+ requirements:
223
+ - - "~>"
224
+ - !ruby/object:Gem::Version
225
+ version: '5'
226
+ type: :development
227
+ prerelease: false
228
+ version_requirements: !ruby/object:Gem::Requirement
229
+ requirements:
230
+ - - "~>"
231
+ - !ruby/object:Gem::Version
232
+ version: '5'
219
233
  - !ruby/object:Gem::Dependency
220
234
  name: actionpack
221
235
  requirement: !ruby/object:Gem::Requirement
@@ -298,6 +312,7 @@ files:
298
312
  - IMPLEMENTATION_DETAILS.md
299
313
  - LICENSE.txt
300
314
  - README.md
315
+ - RUBYZIP_DIFFERENCES.md
301
316
  - Rakefile
302
317
  - bench/buffered_crc32_bench.rb
303
318
  - examples/archive_size_estimate.rb
@@ -319,6 +334,7 @@ files:
319
334
  - lib/zip_kit/rack_chunked_body.rb
320
335
  - lib/zip_kit/rack_tempfile_body.rb
321
336
  - lib/zip_kit/rails_streaming.rb
337
+ - lib/zip_kit/railtie.rb
322
338
  - lib/zip_kit/remote_io.rb
323
339
  - lib/zip_kit/remote_uncap.rb
324
340
  - lib/zip_kit/size_estimator.rb
@@ -358,7 +374,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
358
374
  - !ruby/object:Gem::Version
359
375
  version: '0'
360
376
  requirements: []
361
- rubygems_version: 3.1.6
377
+ rubygems_version: 3.0.3
362
378
  signing_key:
363
379
  specification_version: 4
364
380
  summary: Stream out ZIP files from Ruby. Successor to zip_tricks.