rubyzip 2.4.1 → 3.6.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 +4 -4
- data/Changelog.md +538 -0
- data/LICENSE.md +24 -0
- data/README.md +222 -43
- data/Rakefile +15 -13
- data/lib/rubyzip.rb +3 -0
- data/lib/zip/central_directory.rb +194 -125
- data/lib/zip/compressor.rb +3 -1
- data/lib/zip/constants.rb +29 -21
- data/lib/zip/crypto/aes_encryption.rb +123 -0
- data/lib/zip/crypto/decrypted_io.rb +27 -15
- data/lib/zip/crypto/encryption.rb +4 -2
- data/lib/zip/crypto/null_encryption.rb +5 -13
- data/lib/zip/crypto/traditional_encryption.rb +13 -7
- data/lib/zip/decompressor.rb +4 -3
- data/lib/zip/deflater.rb +12 -8
- data/lib/zip/dirtyable.rb +32 -0
- data/lib/zip/dos_time.rb +64 -6
- data/lib/zip/entry.rb +396 -269
- data/lib/zip/entry_set.rb +11 -9
- data/lib/zip/errors.rb +152 -16
- data/lib/zip/extra_field/aes.rb +50 -0
- data/lib/zip/extra_field/generic.rb +10 -11
- data/lib/zip/extra_field/ntfs.rb +6 -4
- data/lib/zip/extra_field/old_unix.rb +5 -3
- data/lib/zip/extra_field/universal_time.rb +3 -1
- data/lib/zip/extra_field/unix.rb +7 -5
- data/lib/zip/extra_field/unknown.rb +35 -0
- data/lib/zip/extra_field/zip64.rb +19 -5
- data/lib/zip/extra_field.rb +25 -23
- data/lib/zip/file.rb +174 -267
- data/lib/zip/file_split.rb +91 -0
- data/lib/zip/filesystem/dir.rb +86 -0
- data/lib/zip/filesystem/directory_iterator.rb +48 -0
- data/lib/zip/filesystem/file.rb +263 -0
- data/lib/zip/filesystem/file_stat.rb +110 -0
- data/lib/zip/filesystem/zip_file_name_mapper.rb +81 -0
- data/lib/zip/filesystem.rb +27 -596
- data/lib/zip/inflater.rb +13 -10
- data/lib/zip/input_stream.rb +99 -60
- data/lib/zip/ioextras/abstract_input_stream.rb +146 -58
- data/lib/zip/ioextras/abstract_output_stream.rb +13 -3
- data/lib/zip/ioextras.rb +11 -8
- data/lib/zip/null_compressor.rb +3 -1
- data/lib/zip/null_decompressor.rb +6 -3
- data/lib/zip/null_input_stream.rb +3 -1
- data/lib/zip/output_stream.rb +68 -59
- data/lib/zip/pass_thru_compressor.rb +3 -1
- data/lib/zip/pass_thru_decompressor.rb +12 -9
- data/lib/zip/streamable_directory.rb +3 -1
- data/lib/zip/streamable_stream.rb +4 -1
- data/lib/zip/version.rb +4 -1
- data/lib/zip.rb +28 -23
- data/rubyzip.gemspec +39 -0
- data/samples/example.rb +8 -3
- data/samples/example_filesystem.rb +3 -2
- data/samples/example_recursive.rb +3 -1
- data/samples/gtk_ruby_zip.rb +5 -3
- data/samples/qtzip.rb +7 -6
- data/samples/write_simple.rb +2 -1
- data/samples/zipfind.rb +1 -0
- metadata +87 -52
- data/TODO +0 -15
- data/lib/zip/extra_field/zip64_placeholder.rb +0 -15
data/lib/zip/output_stream.rb
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'forwardable'
|
|
4
|
+
|
|
5
|
+
##
|
|
1
6
|
module Zip
|
|
2
7
|
# ZipOutputStream is the basic class for writing zip files. It is
|
|
3
8
|
# possible to create a ZipOutputStream object directly, passing
|
|
@@ -16,57 +21,58 @@ module Zip
|
|
|
16
21
|
#
|
|
17
22
|
# java.util.zip.ZipOutputStream is the original inspiration for this
|
|
18
23
|
# class.
|
|
19
|
-
|
|
20
24
|
class OutputStream
|
|
25
|
+
extend Forwardable
|
|
21
26
|
include ::Zip::IOExtras::AbstractOutputStream
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
def_delegators :@cdir, :comment, :comment=
|
|
24
29
|
|
|
25
30
|
# Opens the indicated zip file. If a file with that name already
|
|
26
31
|
# exists it will be overwritten.
|
|
27
|
-
def initialize(file_name,
|
|
32
|
+
def initialize(file_name, stream: false, encrypter: nil, suppress_extra_fields: false)
|
|
28
33
|
super()
|
|
29
|
-
|
|
30
|
-
Zip.warn_about_v3_api('Zip::OutputStream.new') if dep_stream || !dep_encrypter.nil?
|
|
31
|
-
|
|
32
34
|
@file_name = file_name
|
|
33
|
-
@output_stream = if stream
|
|
34
|
-
iostream = @file_name.dup
|
|
35
|
+
@output_stream = if stream
|
|
36
|
+
iostream = Zip::RUNNING_ON_WINDOWS ? @file_name : @file_name.dup
|
|
35
37
|
iostream.reopen(@file_name)
|
|
36
38
|
iostream.rewind
|
|
37
39
|
iostream
|
|
38
40
|
else
|
|
39
41
|
::File.new(@file_name, 'wb')
|
|
40
42
|
end
|
|
41
|
-
@
|
|
43
|
+
@cdir = ::Zip::CentralDirectory.new
|
|
42
44
|
@compressor = ::Zip::NullCompressor.instance
|
|
43
|
-
@encrypter = encrypter ||
|
|
45
|
+
@encrypter = encrypter || ::Zip::NullEncrypter.new
|
|
46
|
+
@suppress_extra_fields = suppress_extra_fields
|
|
44
47
|
@closed = false
|
|
45
48
|
@current_entry = nil
|
|
46
|
-
@comment = nil
|
|
47
49
|
end
|
|
48
50
|
|
|
49
|
-
# Same as #initialize but if a block is passed the opened
|
|
50
|
-
# stream is passed to the block and closed when the block
|
|
51
|
-
# returns.
|
|
52
51
|
class << self
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
# Same as #initialize but if a block is passed the opened
|
|
53
|
+
# stream is passed to the block and closed when the block
|
|
54
|
+
# returns.
|
|
55
|
+
def open(file_name, encrypter: nil, suppress_extra_fields: false)
|
|
56
|
+
unless block_given?
|
|
57
|
+
return new(
|
|
58
|
+
file_name,
|
|
59
|
+
encrypter: encrypter,
|
|
60
|
+
suppress_extra_fields: suppress_extra_fields
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
zos = new(file_name, stream: false, encrypter: encrypter,
|
|
65
|
+
suppress_extra_fields: suppress_extra_fields)
|
|
59
66
|
yield zos
|
|
60
67
|
ensure
|
|
61
68
|
zos.close if zos
|
|
62
69
|
end
|
|
63
70
|
|
|
64
71
|
# Same as #open but writes to a filestream instead
|
|
65
|
-
def write_buffer(io = ::StringIO.new,
|
|
66
|
-
Zip.warn_about_v3_api('Zip::OutputStream.write_buffer') unless dep_encrypter.nil?
|
|
67
|
-
|
|
72
|
+
def write_buffer(io = ::StringIO.new, encrypter: nil, suppress_extra_fields: false)
|
|
68
73
|
io.binmode if io.respond_to?(:binmode)
|
|
69
|
-
zos = new(io, stream: true, encrypter:
|
|
74
|
+
zos = new(io, stream: true, encrypter: encrypter,
|
|
75
|
+
suppress_extra_fields: suppress_extra_fields)
|
|
70
76
|
yield zos
|
|
71
77
|
zos.close_buffer
|
|
72
78
|
end
|
|
@@ -78,7 +84,7 @@ module Zip
|
|
|
78
84
|
|
|
79
85
|
finalize_current_entry
|
|
80
86
|
update_local_headers
|
|
81
|
-
|
|
87
|
+
@cdir.write_to_stream(@output_stream, suppress_extra_fields: @suppress_extra_fields)
|
|
82
88
|
@output_stream.close
|
|
83
89
|
@closed = true
|
|
84
90
|
end
|
|
@@ -89,37 +95,41 @@ module Zip
|
|
|
89
95
|
|
|
90
96
|
finalize_current_entry
|
|
91
97
|
update_local_headers
|
|
92
|
-
|
|
98
|
+
@cdir.write_to_stream(@output_stream, suppress_extra_fields: @suppress_extra_fields)
|
|
93
99
|
@closed = true
|
|
100
|
+
@output_stream.flush
|
|
94
101
|
@output_stream
|
|
95
102
|
end
|
|
96
103
|
|
|
97
104
|
# Closes the current entry and opens a new for writing.
|
|
98
105
|
# +entry+ can be a ZipEntry object or a string.
|
|
99
|
-
def put_next_entry(
|
|
106
|
+
def put_next_entry(
|
|
107
|
+
entry_name, comment = '', extra = ExtraField.new,
|
|
108
|
+
compression_method = Entry::DEFLATED, level = Zip.default_compression
|
|
109
|
+
)
|
|
100
110
|
raise Error, 'zip stream is closed' if @closed
|
|
101
111
|
|
|
102
|
-
new_entry =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
init_next_entry(new_entry
|
|
112
|
+
new_entry =
|
|
113
|
+
if entry_name.kind_of?(Entry) || entry_name.kind_of?(StreamableStream)
|
|
114
|
+
entry_name
|
|
115
|
+
else
|
|
116
|
+
Entry.new(
|
|
117
|
+
@file_name, entry_name.to_s, comment: comment, extra: extra,
|
|
118
|
+
compression_method: compression_method, compression_level: level
|
|
119
|
+
)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
init_next_entry(new_entry)
|
|
113
123
|
@current_entry = new_entry
|
|
114
124
|
end
|
|
115
125
|
|
|
116
|
-
def copy_raw_entry(entry)
|
|
126
|
+
def copy_raw_entry(entry) # :nodoc:
|
|
117
127
|
entry = entry.dup
|
|
118
128
|
raise Error, 'zip stream is closed' if @closed
|
|
119
129
|
raise Error, 'entry is not a ZipEntry' unless entry.kind_of?(Entry)
|
|
120
130
|
|
|
121
131
|
finalize_current_entry
|
|
122
|
-
@
|
|
132
|
+
@cdir << entry
|
|
123
133
|
src_pos = entry.local_header_offset
|
|
124
134
|
entry.write_local_entry(@output_stream)
|
|
125
135
|
@compressor = NullCompressor.instance
|
|
@@ -138,55 +148,54 @@ module Zip
|
|
|
138
148
|
return unless @current_entry
|
|
139
149
|
|
|
140
150
|
finish
|
|
141
|
-
@current_entry.compressed_size = @output_stream.tell -
|
|
142
|
-
@current_entry.local_header_offset -
|
|
151
|
+
@current_entry.compressed_size = @output_stream.tell -
|
|
152
|
+
@current_entry.local_header_offset -
|
|
143
153
|
@current_entry.calculate_local_header_size
|
|
144
154
|
@current_entry.size = @compressor.size
|
|
145
155
|
@current_entry.crc = @compressor.crc
|
|
146
|
-
@output_stream << @encrypter.data_descriptor(
|
|
156
|
+
@output_stream << @encrypter.data_descriptor(
|
|
157
|
+
@current_entry.crc,
|
|
158
|
+
@current_entry.compressed_size,
|
|
159
|
+
@current_entry.size
|
|
160
|
+
)
|
|
147
161
|
@current_entry.gp_flags |= @encrypter.gp_flags
|
|
148
162
|
@current_entry = nil
|
|
149
163
|
@compressor = ::Zip::NullCompressor.instance
|
|
150
164
|
end
|
|
151
165
|
|
|
152
|
-
def init_next_entry(entry
|
|
166
|
+
def init_next_entry(entry)
|
|
153
167
|
finalize_current_entry
|
|
154
|
-
@
|
|
155
|
-
entry.write_local_entry(@output_stream)
|
|
168
|
+
@cdir << entry
|
|
169
|
+
entry.write_local_entry(@output_stream, suppress_extra_fields: @suppress_extra_fields)
|
|
156
170
|
@encrypter.reset!
|
|
157
171
|
@output_stream << @encrypter.header(entry.mtime)
|
|
158
|
-
@compressor = get_compressor(entry
|
|
172
|
+
@compressor = get_compressor(entry)
|
|
159
173
|
end
|
|
160
174
|
|
|
161
|
-
def get_compressor(entry
|
|
175
|
+
def get_compressor(entry)
|
|
162
176
|
case entry.compression_method
|
|
163
177
|
when Entry::DEFLATED
|
|
164
|
-
::Zip::Deflater.new(@output_stream,
|
|
178
|
+
::Zip::Deflater.new(@output_stream, entry.compression_level, @encrypter)
|
|
165
179
|
when Entry::STORED
|
|
166
180
|
::Zip::PassThruCompressor.new(@output_stream)
|
|
167
181
|
else
|
|
168
|
-
raise ::Zip::CompressionMethodError,
|
|
169
|
-
"Invalid compression method: '#{entry.compression_method}'"
|
|
182
|
+
raise ::Zip::CompressionMethodError, entry.compression_method
|
|
170
183
|
end
|
|
171
184
|
end
|
|
172
185
|
|
|
173
186
|
def update_local_headers
|
|
174
187
|
pos = @output_stream.pos
|
|
175
|
-
@
|
|
188
|
+
@cdir.each do |entry|
|
|
176
189
|
@output_stream.pos = entry.local_header_offset
|
|
177
|
-
entry.write_local_entry(@output_stream,
|
|
190
|
+
entry.write_local_entry(@output_stream, suppress_extra_fields: @suppress_extra_fields,
|
|
191
|
+
rewrite: true)
|
|
178
192
|
end
|
|
179
193
|
@output_stream.pos = pos
|
|
180
194
|
end
|
|
181
195
|
|
|
182
|
-
def write_central_directory
|
|
183
|
-
cdir = CentralDirectory.new(@entry_set, @comment)
|
|
184
|
-
cdir.write_to_stream(@output_stream)
|
|
185
|
-
end
|
|
186
|
-
|
|
187
196
|
protected
|
|
188
197
|
|
|
189
|
-
def finish
|
|
198
|
+
def finish # :nodoc:
|
|
190
199
|
@compressor.finish
|
|
191
200
|
end
|
|
192
201
|
|
|
@@ -1,26 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Zip
|
|
2
|
-
class PassThruDecompressor < Decompressor
|
|
4
|
+
class PassThruDecompressor < Decompressor # :nodoc:all
|
|
3
5
|
def initialize(*args)
|
|
4
6
|
super
|
|
5
7
|
@read_so_far = 0
|
|
6
8
|
end
|
|
7
9
|
|
|
8
|
-
def read(
|
|
9
|
-
return (
|
|
10
|
+
def read(maxlen = nil)
|
|
11
|
+
return (maxlen.nil? || maxlen.zero? ? '' : nil) if eof?
|
|
10
12
|
|
|
11
|
-
if
|
|
12
|
-
|
|
13
|
+
if maxlen.nil? || (@read_so_far + maxlen) > decompressed_size
|
|
14
|
+
maxlen = decompressed_size - @read_so_far
|
|
13
15
|
end
|
|
14
16
|
|
|
15
|
-
@read_so_far +=
|
|
16
|
-
input_stream.read(
|
|
17
|
+
@read_so_far += maxlen
|
|
18
|
+
input_stream.read(maxlen)
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
def eof
|
|
21
|
+
def eof?
|
|
20
22
|
@read_so_far >= decompressed_size
|
|
21
23
|
end
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
# Alias for compatibility. Remove for version 4.
|
|
26
|
+
alias eof eof?
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_STORE, ::Zip::PassThruDecompressor)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Zip
|
|
2
4
|
class StreamableStream < DelegateClass(Entry) # :nodoc:all
|
|
3
5
|
def initialize(entry)
|
|
4
|
-
super
|
|
6
|
+
super
|
|
5
7
|
@temp_file = Tempfile.new(::File.basename(name))
|
|
6
8
|
@temp_file.binmode
|
|
7
9
|
end
|
|
@@ -42,6 +44,7 @@ module Zip
|
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def clean_up
|
|
47
|
+
super
|
|
45
48
|
@temp_file.unlink
|
|
46
49
|
end
|
|
47
50
|
end
|
data/lib/zip/version.rb
CHANGED
data/lib/zip.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'English'
|
|
2
4
|
require 'delegate'
|
|
3
5
|
require 'singleton'
|
|
@@ -5,6 +7,7 @@ require 'tempfile'
|
|
|
5
7
|
require 'fileutils'
|
|
6
8
|
require 'stringio'
|
|
7
9
|
require 'zlib'
|
|
10
|
+
require 'zip/version'
|
|
8
11
|
require 'zip/constants'
|
|
9
12
|
require 'zip/dos_time'
|
|
10
13
|
require 'zip/ioextras'
|
|
@@ -27,33 +30,21 @@ require 'zip/crypto/decrypted_io'
|
|
|
27
30
|
require 'zip/crypto/encryption'
|
|
28
31
|
require 'zip/crypto/null_encryption'
|
|
29
32
|
require 'zip/crypto/traditional_encryption'
|
|
33
|
+
require 'zip/crypto/aes_encryption'
|
|
30
34
|
require 'zip/inflater'
|
|
31
35
|
require 'zip/deflater'
|
|
32
36
|
require 'zip/streamable_stream'
|
|
33
37
|
require 'zip/streamable_directory'
|
|
34
38
|
require 'zip/errors'
|
|
35
39
|
|
|
40
|
+
# Rubyzip is a ruby module for reading and writing zip files.
|
|
41
|
+
#
|
|
42
|
+
# The main entry points are File, InputStream and OutputStream. For a
|
|
43
|
+
# file/directory interface in the style of the standard ruby ::File and
|
|
44
|
+
# ::Dir APIs then `require 'zip/filesystem'` and see FileSystem.
|
|
36
45
|
module Zip
|
|
37
|
-
V3_API_WARNING_MSG = <<~END_MSG
|
|
38
|
-
You have called '%s' (from %s).
|
|
39
|
-
This method is changing or deprecated in version 3.0.0. Please see
|
|
40
|
-
https://github.com/rubyzip/rubyzip/wiki/Updating-to-version-3.x
|
|
41
|
-
for more information.
|
|
42
|
-
END_MSG
|
|
43
|
-
|
|
44
|
-
def self.warn_about_v3_api(method)
|
|
45
|
-
return unless ENV['RUBYZIP_V3_API_WARN']
|
|
46
|
-
|
|
47
|
-
loc = caller_locations(2, 1)[0]
|
|
48
|
-
from = "#{loc.path.split('/').last}:#{loc.lineno}"
|
|
49
|
-
warn format(V3_API_WARNING_MSG, method, from)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
if ENV['RUBYZIP_V3_API_WARN'] && RUBY_VERSION < '3.0'
|
|
53
|
-
warn 'RubyZip 3.0 will require Ruby 3.0 or later.'
|
|
54
|
-
end
|
|
55
|
-
|
|
56
46
|
extend self
|
|
47
|
+
|
|
57
48
|
attr_accessor :unicode_names,
|
|
58
49
|
:on_exists_proc,
|
|
59
50
|
:continue_on_exists_proc,
|
|
@@ -63,21 +54,35 @@ module Zip
|
|
|
63
54
|
:warn_invalid_date,
|
|
64
55
|
:case_insensitive_match,
|
|
65
56
|
:force_entry_names_encoding,
|
|
66
|
-
:validate_entry_sizes
|
|
57
|
+
:validate_entry_sizes,
|
|
58
|
+
:validate_declared_number_of_entries
|
|
59
|
+
|
|
60
|
+
DEFAULT_RESTORE_OPTIONS = {
|
|
61
|
+
restore_ownership: false,
|
|
62
|
+
restore_permissions: true,
|
|
63
|
+
restore_times: true
|
|
64
|
+
}.freeze # :nodoc:
|
|
65
|
+
|
|
66
|
+
# :nodoc:
|
|
67
|
+
# Remove this when JRuby#3962 is fixed.
|
|
68
|
+
ZLIB_FLUSHING_STRATEGY = defined?(JRUBY_VERSION) ? Zlib::SYNC_FLUSH : Zlib::NO_FLUSH
|
|
67
69
|
|
|
68
|
-
def reset!
|
|
70
|
+
def reset! # :nodoc:
|
|
69
71
|
@_ran_once = false
|
|
70
72
|
@unicode_names = false
|
|
71
73
|
@on_exists_proc = false
|
|
72
74
|
@continue_on_exists_proc = false
|
|
73
75
|
@sort_entries = false
|
|
74
|
-
@default_compression =
|
|
75
|
-
@write_zip64_support =
|
|
76
|
+
@default_compression = Zlib::DEFAULT_COMPRESSION
|
|
77
|
+
@write_zip64_support = true
|
|
76
78
|
@warn_invalid_date = true
|
|
77
79
|
@case_insensitive_match = false
|
|
80
|
+
@force_entry_names_encoding = nil
|
|
78
81
|
@validate_entry_sizes = true
|
|
82
|
+
@validate_declared_number_of_entries = false # Set this to `true` in v4.0.0?
|
|
79
83
|
end
|
|
80
84
|
|
|
85
|
+
# Set options for RubyZip in one block.
|
|
81
86
|
def setup
|
|
82
87
|
yield self unless @_ran_once
|
|
83
88
|
@_ran_once = true
|
data/rubyzip.gemspec
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/zip/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = 'rubyzip'
|
|
7
|
+
s.version = Zip::VERSION
|
|
8
|
+
s.authors = ['Robert Haines', 'John Lees-Miller', 'Alexander Simonov']
|
|
9
|
+
s.email = [
|
|
10
|
+
'hainesr@gmail.com', 'jdleesmiller@gmail.com', 'alex@simonov.me'
|
|
11
|
+
]
|
|
12
|
+
s.homepage = 'http://github.com/rubyzip/rubyzip'
|
|
13
|
+
s.platform = Gem::Platform::RUBY
|
|
14
|
+
s.summary = 'rubyzip is a ruby module for reading and writing zip files'
|
|
15
|
+
s.files = Dir.glob('{samples,lib}/**/*.rb') +
|
|
16
|
+
%w[LICENSE.md README.md Changelog.md Rakefile rubyzip.gemspec]
|
|
17
|
+
s.require_paths = ['lib']
|
|
18
|
+
s.license = 'BSD-2-Clause'
|
|
19
|
+
|
|
20
|
+
s.metadata = {
|
|
21
|
+
'bug_tracker_uri' => 'https://github.com/rubyzip/rubyzip/issues',
|
|
22
|
+
'changelog_uri' => "https://github.com/rubyzip/rubyzip/blob/v#{s.version}/Changelog.md",
|
|
23
|
+
'documentation_uri' => "https://www.rubydoc.info/gems/rubyzip/#{s.version}",
|
|
24
|
+
'source_code_uri' => "https://github.com/rubyzip/rubyzip/tree/v#{s.version}",
|
|
25
|
+
'wiki_uri' => 'https://github.com/rubyzip/rubyzip/wiki',
|
|
26
|
+
'rubygems_mfa_required' => 'true'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
s.required_ruby_version = '>= 3.0'
|
|
30
|
+
|
|
31
|
+
s.add_development_dependency 'minitest', '~> 5.25'
|
|
32
|
+
s.add_development_dependency 'rake', '~> 13.2'
|
|
33
|
+
s.add_development_dependency 'rdoc', '~> 6.11'
|
|
34
|
+
s.add_development_dependency 'rubocop', '~> 1.80.2'
|
|
35
|
+
s.add_development_dependency 'rubocop-performance', '~> 1.26.0'
|
|
36
|
+
s.add_development_dependency 'rubocop-rake', '~> 0.7.1'
|
|
37
|
+
s.add_development_dependency 'simplecov', '~> 0.22.0'
|
|
38
|
+
s.add_development_dependency 'simplecov-lcov', '~> 0.8'
|
|
39
|
+
end
|
data/samples/example.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
$LOAD_PATH << '../lib'
|
|
4
5
|
system('zip example.zip example.rb gtk_ruby_zip.rb')
|
|
@@ -20,7 +21,8 @@ end
|
|
|
20
21
|
|
|
21
22
|
zf = Zip::File.new('example.zip')
|
|
22
23
|
zf.each_with_index do |entry, index|
|
|
23
|
-
puts "entry #{index} is #{entry.name}, size = #{entry.size},
|
|
24
|
+
puts "entry #{index} is #{entry.name}, size = #{entry.size}, " \
|
|
25
|
+
"compressed size = #{entry.compressed_size}"
|
|
24
26
|
# use zf.get_input_stream(entry) to get a ZipInputStream for the entry
|
|
25
27
|
# entry can be the ZipEntry object or any object which has a to_s method that
|
|
26
28
|
# returns the name of the entry.
|
|
@@ -70,8 +72,11 @@ part_zips_count = Zip::File.split('large_zip_file.zip', 2_097_152, false)
|
|
|
70
72
|
puts "Zip file splitted in #{part_zips_count} parts"
|
|
71
73
|
|
|
72
74
|
# Track splitting an archive
|
|
73
|
-
Zip::File.split(
|
|
74
|
-
|
|
75
|
+
Zip::File.split(
|
|
76
|
+
'large_zip_file.zip', 1_048_576, true, 'part_zip_file'
|
|
77
|
+
) do |part_count, part_index, chunk_bytes, segment_bytes|
|
|
78
|
+
puts "#{part_index} of #{part_count} part splitting: " \
|
|
79
|
+
"#{(chunk_bytes.to_f / segment_bytes * 100).to_i}%"
|
|
75
80
|
end
|
|
76
81
|
|
|
77
82
|
# For other examples, look at zip.rb and ziptest.rb
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
$LOAD_PATH << '../lib'
|
|
4
5
|
|
|
@@ -6,9 +7,9 @@ require 'zip/filesystem'
|
|
|
6
7
|
|
|
7
8
|
EXAMPLE_ZIP = 'filesystem.zip'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
FileUtils.rm_f(EXAMPLE_ZIP)
|
|
10
11
|
|
|
11
|
-
Zip::File.open(EXAMPLE_ZIP,
|
|
12
|
+
Zip::File.open(EXAMPLE_ZIP, create: true) do |zf|
|
|
12
13
|
zf.file.open('file1.txt', 'w') { |os| os.write 'first file1.txt' }
|
|
13
14
|
zf.dir.mkdir('dir1')
|
|
14
15
|
zf.dir.chdir('dir1')
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'zip'
|
|
2
4
|
|
|
3
5
|
# This is a simple example which uses rubyzip to
|
|
@@ -21,7 +23,7 @@ class ZipFileGenerator
|
|
|
21
23
|
def write
|
|
22
24
|
entries = Dir.entries(@input_dir) - %w[. ..]
|
|
23
25
|
|
|
24
|
-
::Zip::File.open(@output_file,
|
|
26
|
+
::Zip::File.open(@output_file, create: true) do |zipfile|
|
|
25
27
|
write_entries entries, '', zipfile
|
|
26
28
|
end
|
|
27
29
|
end
|
data/samples/gtk_ruby_zip.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
$LOAD_PATH << '../lib'
|
|
4
5
|
|
|
@@ -9,7 +10,7 @@ require 'zip'
|
|
|
9
10
|
|
|
10
11
|
class MainApp < Gtk::Window
|
|
11
12
|
def initialize
|
|
12
|
-
super
|
|
13
|
+
super
|
|
13
14
|
set_usize(400, 256)
|
|
14
15
|
set_title('rubyzip')
|
|
15
16
|
signal_connect(Gtk::Window::SIGNAL_DESTROY) { Gtk.main_quit }
|
|
@@ -42,7 +43,8 @@ class MainApp < Gtk::Window
|
|
|
42
43
|
end
|
|
43
44
|
|
|
44
45
|
class ButtonPanel < Gtk::HButtonBox
|
|
45
|
-
attr_reader :
|
|
46
|
+
attr_reader :extract_button, :open_button
|
|
47
|
+
|
|
46
48
|
def initialize
|
|
47
49
|
super
|
|
48
50
|
set_layout(Gtk::BUTTONBOX_START)
|
|
@@ -72,7 +74,7 @@ class MainApp < Gtk::Window
|
|
|
72
74
|
@zipfile.each do |entry|
|
|
73
75
|
@clist.append([entry.name,
|
|
74
76
|
entry.size.to_s,
|
|
75
|
-
|
|
77
|
+
"#{100.0 * entry.compressedSize / entry.size}%"])
|
|
76
78
|
end
|
|
77
79
|
end
|
|
78
80
|
end
|
data/samples/qtzip.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
$VERBOSE = true
|
|
4
5
|
|
|
@@ -6,14 +7,14 @@ $LOAD_PATH << '../lib'
|
|
|
6
7
|
|
|
7
8
|
require 'Qt'
|
|
8
9
|
system('rbuic -o zipdialogui.rb zipdialogui.ui')
|
|
9
|
-
require 'zipdialogui
|
|
10
|
+
require 'zipdialogui'
|
|
10
11
|
require 'zip'
|
|
11
12
|
|
|
12
13
|
a = Qt::Application.new(ARGV)
|
|
13
14
|
|
|
14
15
|
class ZipDialog < ZipDialogUI
|
|
15
16
|
def initialize
|
|
16
|
-
super
|
|
17
|
+
super
|
|
17
18
|
connect(child('add_button'), SIGNAL('clicked()'),
|
|
18
19
|
self, SLOT('add_files()'))
|
|
19
20
|
connect(child('extract_button'), SIGNAL('clicked()'),
|
|
@@ -65,14 +66,14 @@ class ZipDialog < ZipDialogUI
|
|
|
65
66
|
end
|
|
66
67
|
puts "selected_items.size = #{selected_items.size}"
|
|
67
68
|
puts "unselected_items.size = #{unselected_items.size}"
|
|
68
|
-
items =
|
|
69
|
+
items = selected_items.empty? ? unselected_items : selected_items
|
|
69
70
|
puts "items.size = #{items.size}"
|
|
70
71
|
|
|
71
72
|
d = Qt::FileDialog.get_existing_directory(nil, self)
|
|
72
|
-
if
|
|
73
|
-
puts 'No directory chosen'
|
|
74
|
-
else
|
|
73
|
+
if d
|
|
75
74
|
zipfile { |zf| items.each { |e| zf.extract(e, File.join(d, e)) } }
|
|
75
|
+
else
|
|
76
|
+
puts 'No directory chosen'
|
|
76
77
|
end
|
|
77
78
|
end
|
|
78
79
|
|
data/samples/write_simple.rb
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
$LOAD_PATH << '../lib'
|
|
4
5
|
|
|
5
6
|
require 'zip'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
Zip::OutputStream.open('simple.zip') do |zos|
|
|
8
9
|
zos.put_next_entry 'entry.txt'
|
|
9
10
|
zos.puts 'Hello world'
|
|
10
11
|
end
|