zip_kit 6.3.5 → 6.3.6

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: 83cdf922faca6692b384bc30ba8290f0f15a4567ebce61fccb792a5b5d7993fc
4
- data.tar.gz: ba3a6fee022ba663d77306850246ac8b33ba5d1e10d81f636ace18cc882dc99f
3
+ metadata.gz: 687884a060911fe25101e41be05bd32f4b50068c2ac592acec9937e5b0912f47
4
+ data.tar.gz: c209fb4839008ca84b956839db24ff65d8ec3ae390c4666aabe34743258409ec
5
5
  SHA512:
6
- metadata.gz: ad24aba7c7359f01a11e94ddd1e469fdac2a77c59ece3a113cacebaf900e1cec9a9eee462b385c05d9f1789f9f5c6b48da5098b060e2c5b2c99cc5e312c4d435
7
- data.tar.gz: 96eb1200ee5bdf95e2c9f6b8f91d856607f7981f0eabf7c5cee75dbb3efa200c7642f0886ffdad1965da123281c9cfe8d545614616702cadf4dc207da83a293d
6
+ metadata.gz: bf6bf944be2ec57fd53950c046f5ed28565c5d97f73edc91fbaf1094319d0c2ad47b0a6c6ae1194e69f7fdab3e85beb479b41755e499497fe7f4ab2423529858
7
+ data.tar.gz: 1d54ad55c06b14297057bc594ff45f74a551b453e9cc5d846595abf238289ed0b7b9175177d089db87bceb9601c9322773a44d4601d3a6b32fb30f331f7bbcff
@@ -37,6 +37,20 @@ jobs:
37
37
  RUBYOPT: "--enable=frozen-string-literal --debug=frozen-string-literal"
38
38
  run: "bundle exec rspec --backtrace --fail-fast"
39
39
 
40
+ test_ractors:
41
+ name: "Ractor tests (Ruby 4.0)"
42
+ runs-on: ubuntu-22.04
43
+ steps:
44
+ - name: Checkout
45
+ uses: actions/checkout@v4
46
+ - name: Setup Ruby
47
+ uses: ruby/setup-ruby@v1
48
+ with:
49
+ ruby-version: '4.0'
50
+ bundler-cache: true
51
+ - name: "Tests"
52
+ run: "bundle exec rspec --backtrace --fail-fast spec/zip_kit/ractor_spec.rb"
53
+
40
54
  lint_baseline_ruby: # We need to use syntax appropriate for the minimum supported Ruby version
41
55
  name: Lint (Ruby 2.6 syntax)
42
56
  runs-on: ubuntu-22.04
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 6.3.6
4
+
5
+ * Fix the end of central directory record counting entries discarded by `rollback!`, which made archives with a rolled back entry unreadable for readers which check the entry count (including `ZipKit::FileReader`).
6
+ * Make ZipKit usable from within Ractors: freeze the computed String constants in `ZipWriter`, `BlockDeflate` and `RackChunkedBody`, and stop defining the raising `BlockWrite` methods with `define_method`. Ractor tests run on Ruby 4.0 in CI.
7
+
3
8
  ## 6.3.5
4
9
 
5
10
  * Make `WriteBuffer#<<` much faster for lots of tiny writes, like the XML fragments written by libraries such as caxlsx. Strings are no longer copied with `String#b` before being appended: on Ruby 3.4+ `String#append_as_bytes` is used, on older Rubies the string is converted only if Ruby refuses to append it. Mixing binary strings and non-ASCII strings still works, and the writable still always receives binary strings.
data/Rakefile CHANGED
@@ -16,6 +16,14 @@ RSpec::Core::RakeTask.new(:spec)
16
16
  task :generate_typedefs do
17
17
  `bundle exec sord rbi/zip_kit.rbi`
18
18
  `bundle exec sord rbi/zip_kit.rbs`
19
+
20
+ # Sord inlines the VERSION literal, which would make every version bump produce a typedef diff
21
+ rbi_path = "rbi/zip_kit.rbi"
22
+ rbi = File.read(rbi_path).sub(/^(\s*)VERSION = T\.let\(.+\)$/, '\1VERSION = T.let(T.unsafe(nil), String)')
23
+ File.write(rbi_path, rbi)
24
+ rbs_path = "rbi/zip_kit.rbs"
25
+ rbs = File.read(rbs_path).sub(/^(\s*)VERSION: untyped$/, '\1VERSION: String')
26
+ File.write(rbs_path, rbs)
19
27
  end
20
28
 
21
29
  task default: [:spec, :standard, :generate_typedefs]
@@ -47,7 +47,7 @@
47
47
 
48
48
  class ZipKit::BlockDeflate
49
49
  DEFAULT_BLOCKSIZE = 1_024 * 1024 * 5
50
- END_MARKER = [3, 0].pack("C*")
50
+ END_MARKER = [3, 0].pack("C*").freeze
51
51
  # Zlib::NO_COMPRESSION..
52
52
  VALID_COMPRESSIONS = (Zlib::DEFAULT_COMPRESSION..Zlib::BEST_COMPRESSION).to_a.freeze
53
53
  # Write the end marker (\x3\x0) to the given IO.
@@ -27,11 +27,18 @@ class ZipKit::BlockWrite
27
27
  @block = block
28
28
  end
29
29
 
30
- # Make sure those methods raise outright
31
- %i[seek pos= to_s].each do |m|
32
- define_method(m) do |*_args|
33
- raise "#{m} not supported - this IO adapter is non-rewindable"
34
- end
30
+ # Make sure those methods raise outright. These are not created with define_method,
31
+ # because methods defined with a block can't be called from a non-main Ractor
32
+ def seek(*)
33
+ raise "seek not supported - this IO adapter is non-rewindable"
34
+ end
35
+
36
+ def pos=(*)
37
+ raise "pos= not supported - this IO adapter is non-rewindable"
38
+ end
39
+
40
+ def to_s(*)
41
+ raise "to_s not supported - this IO adapter is non-rewindable"
35
42
  end
36
43
 
37
44
  # Sends a string through to the block stored in the BlockWrite.
@@ -9,7 +9,7 @@
9
9
  # carry, so we copy it into our code.
10
10
  class ZipKit::RackChunkedBody
11
11
  TERM = "\r\n"
12
- TAIL = "0#{TERM}"
12
+ TAIL = "0\r\n"
13
13
 
14
14
  # @param body[#each] the enumerable that yields bytes, usually a `OutputEnumerator`
15
15
  def initialize(body)
@@ -412,11 +412,10 @@ class ZipKit::Streamer
412
412
  # Record the central directory offset, so that it can be written into the EOCD record
413
413
  cdir_starts_at = @out.tell
414
414
 
415
- # Write out the central directory entries, one for each file
416
- @files.each do |entry|
417
- # Skip fillers which are standing in for broken/incomplete files
418
- next if entry.filler?
419
-
415
+ # Write out the central directory entries, one for each file.
416
+ # Skip fillers which are standing in for broken/incomplete files
417
+ entries = @files.reject(&:filler?)
418
+ entries.each do |entry|
420
419
  @writer.write_central_directory_file_header(io: @out,
421
420
  local_file_header_location: entry.local_header_offset,
422
421
  gp_flags: entry.gp_flags,
@@ -436,7 +435,7 @@ class ZipKit::Streamer
436
435
  @writer.write_end_of_central_directory(io: @out,
437
436
  start_of_central_directory_location: cdir_starts_at,
438
437
  central_directory_size: cdir_size,
439
- num_files_in_archive: @files.length)
438
+ num_files_in_archive: entries.length)
440
439
 
441
440
  # Clear the files so that GC will not have to trace all the way to here to deallocate them
442
441
  @files.clear
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ZipKit
4
- VERSION = "6.3.5"
4
+ VERSION = "6.3.6"
5
5
  end
@@ -29,7 +29,7 @@ require "stringio"
29
29
  class ZipKit::ZipWriter
30
30
  FOUR_BYTE_MAX_UINT = 0xFFFFFFFF
31
31
  TWO_BYTE_MAX_UINT = 0xFFFF
32
- ZIP_KIT_COMMENT = "Written using ZipKit %<version>s" % {version: ZipKit::VERSION}
32
+ ZIP_KIT_COMMENT = ("Written using ZipKit %<version>s" % {version: ZipKit::VERSION}).freeze
33
33
  VERSION_MADE_BY = 52
34
34
  VERSION_NEEDED_TO_EXTRACT = 20
35
35
  VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45
@@ -40,7 +40,7 @@ class ZipKit::ZipWriter
40
40
  MADE_BY_SIGNATURE = begin
41
41
  # A combination of the VERSION_MADE_BY low byte and the OS type high byte
42
42
  os_type = 3 # UNIX
43
- [VERSION_MADE_BY, os_type].pack("CC")
43
+ [VERSION_MADE_BY, os_type].pack("CC").freeze
44
44
  end
45
45
 
46
46
  C_UINT4 = "V" # Encode a 4-byte unsigned little-endian uint
data/rbi/zip_kit.rbi CHANGED
@@ -1,6 +1,6 @@
1
1
  # typed: strong
2
2
  module ZipKit
3
- VERSION = T.let("6.3.5", T.untyped)
3
+ VERSION = T.let(T.unsafe(nil), String)
4
4
 
5
5
  class Railtie < Rails::Railtie
6
6
  end
@@ -942,7 +942,7 @@ module ZipKit
942
942
  class ZipWriter
943
943
  FOUR_BYTE_MAX_UINT = T.let(0xFFFFFFFF, T.untyped)
944
944
  TWO_BYTE_MAX_UINT = T.let(0xFFFF, T.untyped)
945
- ZIP_KIT_COMMENT = T.let("Written using ZipKit %<version>s" % {version: ZipKit::VERSION}, T.untyped)
945
+ ZIP_KIT_COMMENT = T.let(("Written using ZipKit %<version>s" % {version: ZipKit::VERSION}).freeze, T.untyped)
946
946
  VERSION_MADE_BY = T.let(52, T.untyped)
947
947
  VERSION_NEEDED_TO_EXTRACT = T.let(20, T.untyped)
948
948
  VERSION_NEEDED_TO_EXTRACT_ZIP64 = T.let(45, T.untyped)
@@ -953,7 +953,7 @@ module ZipKit
953
953
  MADE_BY_SIGNATURE = T.let(begin
954
954
  # A combination of the VERSION_MADE_BY low byte and the OS type high byte
955
955
  os_type = 3 # UNIX
956
- [VERSION_MADE_BY, os_type].pack("CC")
956
+ [VERSION_MADE_BY, os_type].pack("CC").freeze
957
957
  end, T.untyped)
958
958
  C_UINT4 = T.let("V", T.untyped)
959
959
  C_UINT2 = T.let("v", T.untyped)
@@ -1164,6 +1164,20 @@ end, T.untyped)
1164
1164
  sig { params(block: T.proc.params(bytes: String).void).void }
1165
1165
  def initialize(&block); end
1166
1166
 
1167
+ # sord omit - no YARD return type given, using untyped
1168
+ # Make sure those methods raise outright. These are not created with define_method,
1169
+ # because methods defined with a block can't be called from a non-main Ractor
1170
+ sig { returns(T.untyped) }
1171
+ def seek; end
1172
+
1173
+ # sord omit - no YARD return type given, using untyped
1174
+ sig { returns(T.untyped) }
1175
+ def pos=; end
1176
+
1177
+ # sord omit - no YARD return type given, using untyped
1178
+ sig { returns(T.untyped) }
1179
+ def to_s; end
1180
+
1167
1181
  # Sends a string through to the block stored in the BlockWrite.
1168
1182
  #
1169
1183
  # _@param_ `buf` — the string to write. Note that a zero-length String will not be forwarded to the block, as it has special meaning when used with chunked encoding (it indicates the end of the stream).
@@ -1879,7 +1893,7 @@ end, T.untyped)
1879
1893
  # compressed_string = ZipKit::BlockDeflate.deflate_chunk(big_string)
1880
1894
  class BlockDeflate
1881
1895
  DEFAULT_BLOCKSIZE = T.let(1_024 * 1024 * 5, T.untyped)
1882
- END_MARKER = T.let([3, 0].pack("C*"), T.untyped)
1896
+ END_MARKER = T.let([3, 0].pack("C*").freeze, T.untyped)
1883
1897
  VALID_COMPRESSIONS = T.let((Zlib::DEFAULT_COMPRESSION..Zlib::BEST_COMPRESSION).to_a.freeze, T.untyped)
1884
1898
 
1885
1899
  # Write the end marker (\x3\x0) to the given IO.
@@ -2225,7 +2239,7 @@ end, T.untyped)
2225
2239
  # carry, so we copy it into our code.
2226
2240
  class RackChunkedBody
2227
2241
  TERM = T.let("\r\n", T.untyped)
2228
- TAIL = T.let("0#{TERM}", T.untyped)
2242
+ TAIL = T.let("0\r\n", T.untyped)
2229
2243
 
2230
2244
  # sord duck - #each looks like a duck type, replacing with untyped
2231
2245
  # _@param_ `body` — the enumerable that yields bytes, usually a `OutputEnumerator`
data/rbi/zip_kit.rbs CHANGED
@@ -1,5 +1,5 @@
1
1
  module ZipKit
2
- VERSION: untyped
2
+ VERSION: String
3
3
 
4
4
  class Railtie < Rails::Railtie
5
5
  end
@@ -1038,6 +1038,17 @@ module ZipKit
1038
1038
  # _@param_ `block` — The block that will be called when this object receives the `<<` message
1039
1039
  def initialize: () ?{ (String bytes) -> void } -> void
1040
1040
 
1041
+ # sord omit - no YARD return type given, using untyped
1042
+ # Make sure those methods raise outright. These are not created with define_method,
1043
+ # because methods defined with a block can't be called from a non-main Ractor
1044
+ def seek: () -> untyped
1045
+
1046
+ # sord omit - no YARD return type given, using untyped
1047
+ def pos=: () -> untyped
1048
+
1049
+ # sord omit - no YARD return type given, using untyped
1050
+ def to_s: () -> untyped
1051
+
1041
1052
  # Sends a string through to the block stored in the BlockWrite.
1042
1053
  #
1043
1054
  # _@param_ `buf` — the string to write. Note that a zero-length String will not be forwarded to the block, as it has special meaning when used with chunked encoding (it indicates the end of the stream).
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.3.5
4
+ version: 6.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
@@ -11,7 +11,7 @@ authors:
11
11
  - Felix Bünemann
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2026-09-30 00:00:00.000000000 Z
14
+ date: 2026-10-02 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler