rubyzip 1.1.7 → 2.3.2

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.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +137 -54
  3. data/Rakefile +6 -4
  4. data/lib/zip/central_directory.rb +17 -13
  5. data/lib/zip/compressor.rb +1 -2
  6. data/lib/zip/constants.rb +57 -5
  7. data/lib/zip/crypto/decrypted_io.rb +40 -0
  8. data/lib/zip/crypto/null_encryption.rb +4 -6
  9. data/lib/zip/crypto/traditional_encryption.rb +14 -14
  10. data/lib/zip/decompressor.rb +22 -4
  11. data/lib/zip/deflater.rb +8 -6
  12. data/lib/zip/dos_time.rb +17 -13
  13. data/lib/zip/entry.rb +171 -148
  14. data/lib/zip/entry_set.rb +16 -14
  15. data/lib/zip/errors.rb +3 -0
  16. data/lib/zip/extra_field/generic.rb +14 -13
  17. data/lib/zip/extra_field/ntfs.rb +18 -16
  18. data/lib/zip/extra_field/old_unix.rb +12 -11
  19. data/lib/zip/extra_field/universal_time.rb +46 -16
  20. data/lib/zip/extra_field/unix.rb +10 -9
  21. data/lib/zip/extra_field/zip64.rb +15 -12
  22. data/lib/zip/extra_field/zip64_placeholder.rb +1 -2
  23. data/lib/zip/extra_field.rb +18 -16
  24. data/lib/zip/file.rb +147 -115
  25. data/lib/zip/filesystem.rb +289 -272
  26. data/lib/zip/inflater.rb +24 -36
  27. data/lib/zip/input_stream.rb +44 -28
  28. data/lib/zip/ioextras/abstract_input_stream.rb +24 -17
  29. data/lib/zip/ioextras/abstract_output_stream.rb +4 -6
  30. data/lib/zip/ioextras.rb +2 -4
  31. data/lib/zip/null_compressor.rb +2 -2
  32. data/lib/zip/null_decompressor.rb +3 -11
  33. data/lib/zip/null_input_stream.rb +0 -0
  34. data/lib/zip/output_stream.rb +25 -17
  35. data/lib/zip/pass_thru_compressor.rb +6 -6
  36. data/lib/zip/pass_thru_decompressor.rb +14 -24
  37. data/lib/zip/streamable_directory.rb +3 -3
  38. data/lib/zip/streamable_stream.rb +7 -11
  39. data/lib/zip/version.rb +1 -1
  40. data/lib/zip.rb +15 -6
  41. data/samples/example.rb +29 -39
  42. data/samples/example_filesystem.rb +16 -18
  43. data/samples/example_recursive.rb +31 -25
  44. data/samples/gtk_ruby_zip.rb +84 -0
  45. data/samples/qtzip.rb +23 -32
  46. data/samples/write_simple.rb +10 -13
  47. data/samples/zipfind.rb +33 -40
  48. metadata +50 -141
  49. data/samples/gtkRubyzip.rb +0 -86
  50. data/test/basic_zip_file_test.rb +0 -64
  51. data/test/central_directory_entry_test.rb +0 -73
  52. data/test/central_directory_test.rb +0 -104
  53. data/test/crypto/null_encryption_test.rb +0 -53
  54. data/test/crypto/traditional_encryption_test.rb +0 -80
  55. data/test/data/WarnInvalidDate.zip +0 -0
  56. data/test/data/file1.txt +0 -46
  57. data/test/data/file1.txt.deflatedData +0 -0
  58. data/test/data/file2.txt +0 -1504
  59. data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
  60. data/test/data/globTest/foo.txt +0 -0
  61. data/test/data/globTest/food.txt +0 -0
  62. data/test/data/globTest.zip +0 -0
  63. data/test/data/mimetype +0 -1
  64. data/test/data/notzippedruby.rb +0 -7
  65. data/test/data/ntfs.zip +0 -0
  66. data/test/data/rubycode.zip +0 -0
  67. data/test/data/rubycode2.zip +0 -0
  68. data/test/data/testDirectory.bin +0 -0
  69. data/test/data/zip64-sample.zip +0 -0
  70. data/test/data/zipWithDirs.zip +0 -0
  71. data/test/data/zipWithEncryption.zip +0 -0
  72. data/test/deflater_test.rb +0 -67
  73. data/test/encryption_test.rb +0 -42
  74. data/test/entry_set_test.rb +0 -138
  75. data/test/entry_test.rb +0 -165
  76. data/test/errors_test.rb +0 -36
  77. data/test/extra_field_test.rb +0 -78
  78. data/test/file_extract_directory_test.rb +0 -56
  79. data/test/file_extract_test.rb +0 -90
  80. data/test/file_split_test.rb +0 -60
  81. data/test/file_test.rb +0 -559
  82. data/test/filesystem/dir_iterator_test.rb +0 -62
  83. data/test/filesystem/directory_test.rb +0 -131
  84. data/test/filesystem/file_mutating_test.rb +0 -100
  85. data/test/filesystem/file_nonmutating_test.rb +0 -514
  86. data/test/filesystem/file_stat_test.rb +0 -66
  87. data/test/gentestfiles.rb +0 -134
  88. data/test/inflater_test.rb +0 -14
  89. data/test/input_stream_test.rb +0 -170
  90. data/test/ioextras/abstract_input_stream_test.rb +0 -103
  91. data/test/ioextras/abstract_output_stream_test.rb +0 -106
  92. data/test/ioextras/fake_io_test.rb +0 -18
  93. data/test/local_entry_test.rb +0 -156
  94. data/test/output_stream_test.rb +0 -129
  95. data/test/pass_thru_compressor_test.rb +0 -31
  96. data/test/pass_thru_decompressor_test.rb +0 -15
  97. data/test/settings_test.rb +0 -92
  98. data/test/test_helper.rb +0 -228
  99. data/test/unicode_file_names_and_comments_test.rb +0 -52
  100. data/test/zip64_full_test.rb +0 -53
  101. data/test/zip64_support_test.rb +0 -15
data/lib/zip/file.rb CHANGED
@@ -43,58 +43,84 @@ module Zip
43
43
  # interface for accessing the filesystem, ie. the File and Dir classes.
44
44
 
45
45
  class File < CentralDirectory
46
-
47
- CREATE = 1
46
+ CREATE = true
48
47
  SPLIT_SIGNATURE = 0x08074b50
49
48
  ZIP64_EOCD_SIGNATURE = 0x06064b50
50
- MAX_SEGMENT_SIZE = 3221225472
51
- MIN_SEGMENT_SIZE = 65536
49
+ MAX_SEGMENT_SIZE = 3_221_225_472
50
+ MIN_SEGMENT_SIZE = 65_536
52
51
  DATA_BUFFER_SIZE = 8192
52
+ IO_METHODS = [:tell, :seek, :read, :eof, :close]
53
+
54
+ DEFAULT_OPTIONS = {
55
+ restore_ownership: false,
56
+ restore_permissions: false,
57
+ restore_times: false
58
+ }.freeze
53
59
 
54
60
  attr_reader :name
55
61
 
56
- # default -> false
62
+ # default -> false.
57
63
  attr_accessor :restore_ownership
58
- # default -> false
64
+
65
+ # default -> false, but will be set to true in a future version.
59
66
  attr_accessor :restore_permissions
60
- # default -> true
67
+
68
+ # default -> false, but will be set to true in a future version.
61
69
  attr_accessor :restore_times
70
+
62
71
  # Returns the zip files comment, if it has one
63
72
  attr_accessor :comment
64
73
 
65
74
  # Opens a zip archive. Pass true as the second parameter to create
66
75
  # a new archive if it doesn't exist already.
67
- def initialize(file_name, create = nil, buffer = false, options = {})
76
+ def initialize(path_or_io, create = false, buffer = false, options = {})
68
77
  super()
69
- @name = file_name
78
+ options = DEFAULT_OPTIONS.merge(options)
79
+ @name = path_or_io.respond_to?(:path) ? path_or_io.path : path_or_io
70
80
  @comment = ''
71
- @create = create
72
- case
73
- when !buffer && ::File.size?(file_name)
74
- @create = nil
75
- @exist_file_perms = ::File.stat(file_name).mode
76
- ::File.open(name, 'rb') do |f|
77
- read_from_stream(f)
81
+ @create = create ? true : false # allow any truthy value to mean true
82
+
83
+ if ::File.size?(@name.to_s)
84
+ # There is a file, which exists, that is associated with this zip.
85
+ @create = false
86
+ @file_permissions = ::File.stat(@name).mode
87
+
88
+ if buffer
89
+ read_from_stream(path_or_io)
90
+ else
91
+ ::File.open(@name, 'rb') do |f|
92
+ read_from_stream(f)
93
+ end
78
94
  end
79
- when create
95
+ elsif buffer && path_or_io.size > 0
96
+ # This zip is probably a non-empty StringIO.
97
+ read_from_stream(path_or_io)
98
+ elsif @create
99
+ # This zip is completely new/empty and is to be created.
80
100
  @entry_set = EntrySet.new
101
+ elsif ::File.zero?(@name)
102
+ # A file exists, but it is empty.
103
+ raise Error, "File #{@name} has zero size. Did you mean to pass the create flag?"
81
104
  else
82
- raise Error, "File #{file_name} not found"
105
+ # Everything is wrong.
106
+ raise Error, "File #{@name} not found"
83
107
  end
108
+
84
109
  @stored_entries = @entry_set.dup
85
110
  @stored_comment = @comment
86
- @restore_ownership = options[:restore_ownership] || false
87
- @restore_permissions = options[:restore_permissions] || true
88
- @restore_times = options[:restore_times] || true
111
+ @restore_ownership = options[:restore_ownership]
112
+ @restore_permissions = options[:restore_permissions]
113
+ @restore_times = options[:restore_times]
89
114
  end
90
115
 
91
116
  class << self
92
- # Same as #new. If a block is passed the ZipFile object is passed
93
- # to the block and is automatically closed afterwards just as with
94
- # ruby's builtin File.open method.
95
- def open(file_name, create = nil)
96
- zf = ::Zip::File.new(file_name, create)
117
+ # Similar to ::new. If a block is passed the Zip::File object is passed
118
+ # to the block and is automatically closed afterwards, just as with
119
+ # ruby's builtin File::open method.
120
+ def open(file_name, create = false, options = {})
121
+ zf = ::Zip::File.new(file_name, create, false, options)
97
122
  return zf unless block_given?
123
+
98
124
  begin
99
125
  yield zf
100
126
  ensure
@@ -115,23 +141,24 @@ module Zip
115
141
  # (This can be used to extract data from a
116
142
  # downloaded zip archive without first saving it to disk.)
117
143
  def open_buffer(io, options = {})
118
- unless io.is_a?(IO) || io.is_a?(String) || io.is_a?(Tempfile)
119
- raise "Zip::File.open_buffer expects an argument of class String, IO, or Tempfile. Found: #{io.class}"
120
- end
121
- if io.is_a?(::String)
122
- require 'stringio'
123
- io = ::StringIO.new(io)
124
- elsif io.is_a?(IO)
125
- # https://github.com/rubyzip/rubyzip/issues/119
126
- io.binmode
144
+ unless IO_METHODS.map { |method| io.respond_to?(method) }.all? || io.kind_of?(String)
145
+ raise "Zip::File.open_buffer expects a String or IO-like argument (responds to #{IO_METHODS.join(', ')}). Found: #{io.class}"
127
146
  end
147
+
148
+ io = ::StringIO.new(io) if io.kind_of?(::String)
149
+
150
+ # https://github.com/rubyzip/rubyzip/issues/119
151
+ io.binmode if io.respond_to?(:binmode)
152
+
128
153
  zf = ::Zip::File.new(io, true, true, options)
129
- zf.read_from_stream(io)
154
+ return zf unless block_given?
155
+
130
156
  yield zf
157
+
131
158
  begin
132
159
  zf.write_buffer(io)
133
160
  rescue IOError => e
134
- raise unless e.message == "not opened for writing"
161
+ raise unless e.message == 'not opened for writing'
135
162
  end
136
163
  end
137
164
 
@@ -141,17 +168,16 @@ module Zip
141
168
  # whereas ZipInputStream jumps through the entire archive accessing the
142
169
  # local entry headers (which contain the same information as the
143
170
  # central directory).
144
- def foreach(aZipFileName, &block)
145
- open(aZipFileName) do |zipFile|
146
- zipFile.each(&block)
171
+ def foreach(zip_file_name, &block)
172
+ ::Zip::File.open(zip_file_name) do |zip_file|
173
+ zip_file.each(&block)
147
174
  end
148
175
  end
149
176
 
150
177
  def get_segment_size_for_split(segment_size)
151
- case
152
- when MIN_SEGMENT_SIZE > segment_size
178
+ if MIN_SEGMENT_SIZE > segment_size
153
179
  MIN_SEGMENT_SIZE
154
- when MAX_SEGMENT_SIZE < segment_size
180
+ elsif MAX_SEGMENT_SIZE < segment_size
155
181
  MAX_SEGMENT_SIZE
156
182
  else
157
183
  segment_size
@@ -159,8 +185,10 @@ module Zip
159
185
  end
160
186
 
161
187
  def get_partial_zip_file_name(zip_file_name, partial_zip_file_name)
162
- partial_zip_file_name = zip_file_name.sub(/#{::File.basename(zip_file_name)}\z/,
163
- partial_zip_file_name + ::File.extname(zip_file_name)) unless partial_zip_file_name.nil?
188
+ unless partial_zip_file_name.nil?
189
+ partial_zip_file_name = zip_file_name.sub(/#{::File.basename(zip_file_name)}\z/,
190
+ partial_zip_file_name + ::File.extname(zip_file_name))
191
+ end
164
192
  partial_zip_file_name ||= zip_file_name
165
193
  partial_zip_file_name
166
194
  end
@@ -181,7 +209,7 @@ module Zip
181
209
  def save_splited_part(zip_file, partial_zip_file_name, zip_file_size, szip_file_index, segment_size, segment_count)
182
210
  ssegment_size = zip_file_size - zip_file.pos
183
211
  ssegment_size = segment_size if ssegment_size > segment_size
184
- szip_file_name = "#{partial_zip_file_name}.#{'%03d'%(szip_file_index)}"
212
+ szip_file_name = "#{partial_zip_file_name}.#{format('%03d', szip_file_index)}"
185
213
  ::File.open(szip_file_name, 'wb') do |szip_file|
186
214
  if szip_file_index == 1
187
215
  ssegment_size = put_split_signature(szip_file, segment_size)
@@ -191,7 +219,7 @@ module Zip
191
219
  segment_bytes_left = ssegment_size - chunk_bytes
192
220
  buffer_size = segment_bytes_left < DATA_BUFFER_SIZE ? segment_bytes_left : DATA_BUFFER_SIZE
193
221
  chunk = zip_file.read(buffer_size)
194
- chunk_bytes += buffer_size
222
+ chunk_bytes += buffer_size
195
223
  szip_file << chunk
196
224
  # Info for track splitting
197
225
  yield segment_count, szip_file_index, chunk_bytes, ssegment_size if block_given?
@@ -203,12 +231,14 @@ module Zip
203
231
  def split(zip_file_name, segment_size = MAX_SEGMENT_SIZE, delete_zip_file = true, partial_zip_file_name = nil)
204
232
  raise Error, "File #{zip_file_name} not found" unless ::File.exist?(zip_file_name)
205
233
  raise Errno::ENOENT, zip_file_name unless ::File.readable?(zip_file_name)
234
+
206
235
  zip_file_size = ::File.size(zip_file_name)
207
236
  segment_size = get_segment_size_for_split(segment_size)
208
237
  return if zip_file_size <= segment_size
238
+
209
239
  segment_count = get_segment_count_for_split(zip_file_size, segment_size)
210
240
  # Checking for correct zip structure
211
- self.open(zip_file_name) {}
241
+ ::Zip::File.open(zip_file_name) {}
212
242
  partial_zip_file_name = get_partial_zip_file_name(zip_file_name, partial_zip_file_name)
213
243
  szip_file_index = 0
214
244
  ::File.open(zip_file_name, 'rb') do |zip_file|
@@ -222,12 +252,11 @@ module Zip
222
252
  end
223
253
  end
224
254
 
225
-
226
255
  # Returns an input stream to the specified entry. If a block is passed
227
256
  # the stream object is passed to the block and the stream is automatically
228
257
  # closed afterwards just as with ruby's builtin File.open method.
229
- def get_input_stream(entry, &aProc)
230
- get_entry(entry).get_input_stream(&aProc)
258
+ def get_input_stream(entry, &a_proc)
259
+ get_entry(entry).get_input_stream(&a_proc)
231
260
  end
232
261
 
233
262
  # Returns an output stream to the specified entry. If entry is not an instance
@@ -235,7 +264,11 @@ module Zip
235
264
  # specified. If a block is passed the stream object is passed to the block and
236
265
  # the stream is automatically closed afterwards just as with ruby's builtin
237
266
  # File.open method.
238
- def get_output_stream(entry, permission_int = nil, comment = nil, extra = nil, compressed_size = nil, crc = nil, compression_method = nil, size = nil, time = nil, &aProc)
267
+ def get_output_stream(entry, permission_int = nil, comment = nil,
268
+ extra = nil, compressed_size = nil, crc = nil,
269
+ compression_method = nil, size = nil, time = nil,
270
+ &a_proc)
271
+
239
272
  new_entry =
240
273
  if entry.kind_of?(Entry)
241
274
  entry
@@ -249,7 +282,7 @@ module Zip
249
282
  new_entry.unix_perms = permission_int
250
283
  zip_streamable_entry = StreamableStream.new(new_entry)
251
284
  @entry_set << zip_streamable_entry
252
- zip_streamable_entry.get_output_stream(&aProc)
285
+ zip_streamable_entry.get_output_stream(&a_proc)
253
286
  end
254
287
 
255
288
  # Returns the name of the zip archive
@@ -259,19 +292,26 @@ module Zip
259
292
 
260
293
  # Returns a string containing the contents of the specified entry
261
294
  def read(entry)
262
- get_input_stream(entry) { |is| is.read }
295
+ get_input_stream(entry, &:read)
263
296
  end
264
297
 
265
298
  # Convenience method for adding the contents of a file to the archive
266
299
  def add(entry, src_path, &continue_on_exists_proc)
267
300
  continue_on_exists_proc ||= proc { ::Zip.continue_on_exists_proc }
268
- check_entry_exists(entry, continue_on_exists_proc, "add")
301
+ check_entry_exists(entry, continue_on_exists_proc, 'add')
269
302
  new_entry = entry.kind_of?(::Zip::Entry) ? entry : ::Zip::Entry.new(@name, entry.to_s)
270
303
  new_entry.gather_fileinfo_from_srcpath(src_path)
271
304
  new_entry.dirty = true
272
305
  @entry_set << new_entry
273
306
  end
274
307
 
308
+ # Convenience method for adding the contents of a file to the archive
309
+ # in Stored format (uncompressed)
310
+ def add_stored(entry, src_path, &continue_on_exists_proc)
311
+ entry = ::Zip::Entry.new(@name, entry.to_s, nil, nil, nil, nil, ::Zip::Entry::STORED)
312
+ add(entry, src_path, &continue_on_exists_proc)
313
+ end
314
+
275
315
  # Removes the specified entry.
276
316
  def remove(entry)
277
317
  @entry_set.delete(get_entry(entry))
@@ -279,19 +319,19 @@ module Zip
279
319
 
280
320
  # Renames the specified entry.
281
321
  def rename(entry, new_name, &continue_on_exists_proc)
282
- foundEntry = get_entry(entry)
322
+ found_entry = get_entry(entry)
283
323
  check_entry_exists(new_name, continue_on_exists_proc, 'rename')
284
- @entry_set.delete(foundEntry)
285
- foundEntry.name = new_name
286
- @entry_set << foundEntry
324
+ @entry_set.delete(found_entry)
325
+ found_entry.name = new_name
326
+ @entry_set << found_entry
287
327
  end
288
328
 
289
- # Replaces the specified entry with the contents of srcPath (from
329
+ # Replaces the specified entry with the contents of src_path (from
290
330
  # the file system).
291
- def replace(entry, srcPath)
292
- check_file(srcPath)
331
+ def replace(entry, src_path)
332
+ check_file(src_path)
293
333
  remove(entry)
294
- add(entry, srcPath)
334
+ add(entry, src_path)
295
335
  end
296
336
 
297
337
  # Extracts entry to file dest_path.
@@ -304,7 +344,8 @@ module Zip
304
344
  # Commits changes that has been made since the previous commit to
305
345
  # the zip archive.
306
346
  def commit
307
- return unless commit_required?
347
+ return if name.kind_of?(StringIO) || !commit_required?
348
+
308
349
  on_success_replace do |tmp_file|
309
350
  ::Zip::OutputStream.open(tmp_file) do |zos|
310
351
  @entry_set.each do |e|
@@ -338,13 +379,19 @@ module Zip
338
379
  @entry_set.each do |e|
339
380
  return true if e.dirty
340
381
  end
341
- @comment != @stored_comment || @entry_set != @stored_entries || @create == ::Zip::File::CREATE
382
+ @comment != @stored_comment || @entry_set != @stored_entries || @create
342
383
  end
343
384
 
344
385
  # Searches for entry with the specified name. Returns nil if
345
386
  # no entry is found. See also get_entry
346
387
  def find_entry(entry_name)
347
- @entry_set.find_entry(entry_name)
388
+ selected_entry = @entry_set.find_entry(entry_name)
389
+ return if selected_entry.nil?
390
+
391
+ selected_entry.restore_ownership = @restore_ownership
392
+ selected_entry.restore_permissions = @restore_permissions
393
+ selected_entry.restore_times = @restore_times
394
+ selected_entry
348
395
  end
349
396
 
350
397
  # Searches for entries given a glob
@@ -356,78 +403,63 @@ module Zip
356
403
  # if no entry is found.
357
404
  def get_entry(entry)
358
405
  selected_entry = find_entry(entry)
359
- unless selected_entry
360
- raise Errno::ENOENT, entry
361
- end
362
- selected_entry.restore_ownership = @restore_ownership
363
- selected_entry.restore_permissions = @restore_permissions
364
- selected_entry.restore_times = @restore_times
406
+ raise Errno::ENOENT, entry if selected_entry.nil?
407
+
365
408
  selected_entry
366
409
  end
367
410
 
368
411
  # Creates a directory
369
- def mkdir(entryName, permissionInt = 0755)
370
- if find_entry(entryName)
371
- raise Errno::EEXIST, "File exists - #{entryName}"
372
- end
373
- entryName = entryName.dup.to_s
374
- entryName << '/' unless entryName.end_with?('/')
375
- @entry_set << ::Zip::StreamableDirectory.new(@name, entryName, nil, permissionInt)
412
+ def mkdir(entry_name, permission = 0o755)
413
+ raise Errno::EEXIST, "File exists - #{entry_name}" if find_entry(entry_name)
414
+
415
+ entry_name = entry_name.dup.to_s
416
+ entry_name << '/' unless entry_name.end_with?('/')
417
+ @entry_set << ::Zip::StreamableDirectory.new(@name, entry_name, nil, permission)
376
418
  end
377
419
 
378
420
  private
379
421
 
380
- def is_directory(newEntry, srcPath)
381
- srcPathIsDirectory = ::File.directory?(srcPath)
382
- if newEntry.is_directory && !srcPathIsDirectory
422
+ def directory?(new_entry, src_path)
423
+ path_is_directory = ::File.directory?(src_path)
424
+ if new_entry.directory? && !path_is_directory
383
425
  raise ArgumentError,
384
- "entry name '#{newEntry}' indicates directory entry, but "+
385
- "'#{srcPath}' is not a directory"
386
- elsif !newEntry.is_directory && srcPathIsDirectory
387
- newEntry.name += "/"
426
+ "entry name '#{new_entry}' indicates directory entry, but " \
427
+ "'#{src_path}' is not a directory"
428
+ elsif !new_entry.directory? && path_is_directory
429
+ new_entry.name += '/'
388
430
  end
389
- newEntry.is_directory && srcPathIsDirectory
431
+ new_entry.directory? && path_is_directory
390
432
  end
391
433
 
392
- def check_entry_exists(entryName, continue_on_exists_proc, procedureName)
434
+ def check_entry_exists(entry_name, continue_on_exists_proc, proc_name)
393
435
  continue_on_exists_proc ||= proc { Zip.continue_on_exists_proc }
394
- if @entry_set.include?(entryName)
395
- if continue_on_exists_proc.call
396
- remove get_entry(entryName)
397
- else
398
- raise ::Zip::EntryExistsError,
399
- procedureName + " failed. Entry #{entryName} already exists"
400
- end
436
+ return unless @entry_set.include?(entry_name)
437
+
438
+ if continue_on_exists_proc.call
439
+ remove get_entry(entry_name)
440
+ else
441
+ raise ::Zip::EntryExistsError,
442
+ proc_name + " failed. Entry #{entry_name} already exists"
401
443
  end
402
444
  end
403
445
 
404
446
  def check_file(path)
405
- unless ::File.readable?(path)
406
- raise Errno::ENOENT, path
407
- end
447
+ raise Errno::ENOENT, path unless ::File.readable?(path)
408
448
  end
409
449
 
410
450
  def on_success_replace
411
- tmpfile = get_tempfile
412
- tmp_filename = tmpfile.path
413
- ObjectSpace.undefine_finalizer(tmpfile)
414
- tmpfile.close
415
- if yield tmp_filename
416
- ::File.rename(tmp_filename, self.name)
417
- if defined?(@exist_file_perms)
418
- ::File.chmod(@exist_file_perms, self.name)
451
+ dirname, basename = ::File.split(name)
452
+ ::Dir::Tmpname.create(basename, dirname) do |tmp_filename|
453
+ begin
454
+ if yield tmp_filename
455
+ ::File.rename(tmp_filename, name)
456
+ ::File.chmod(@file_permissions, name) unless @create
457
+ end
458
+ ensure
459
+ ::File.unlink(tmp_filename) if ::File.exist?(tmp_filename)
419
460
  end
420
461
  end
421
- ensure
422
- tmpfile.unlink if tmpfile
423
462
  end
424
-
425
- def get_tempfile
426
- temp_file = Tempfile.new(::File.basename(name), ::File.dirname(name))
427
- temp_file.binmode
428
- temp_file
429
- end
430
-
431
463
  end
432
464
  end
433
465