minitar 0.7 → 0.8

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: fe4dcb6889d7dd3e767dc3329f8e874d4359577f219b0a76df859617a253c4fb
4
- data.tar.gz: 345a765b717201d0a47dbb4d52572d68d51797fb41f7df0f314e9a43b160e6de
3
+ metadata.gz: 1440e1c57cdd811497e6717a6f81791816bfb2ec5dce0981d9208c41bcd6f09d
4
+ data.tar.gz: e36cf70bd9acc32d73c95a48c1e67f494853f47603032cac05a84bd366417655
5
5
  SHA512:
6
- metadata.gz: faf3628dd94d2a9f85c86a7662b8699911d022d5b7e75ea2f41effd6fd896252721e953203796cd99739f7c9e756066250d78e613ee606271d79c36753836df2
7
- data.tar.gz: b0311f7166e41805adce3709c53a0acda7dcfe5b732abb16d278706b5e54b56cb2477e3e51bc0bf8d5f6143e61421fd11860a3e1fca22c57ea405f751fa8b369
6
+ metadata.gz: b615673d6e6626606e6e858d453af056870f4b8c88dade5641595b35733491e6dfe2ec32e90d28f7585308a4229f2ace63b47224c0b2877b44c5b028ee3c1031
7
+ data.tar.gz: ea2adda3fdcf9314c325cfa69f7ae5bbf6bc02732c8b131acef7406c45c4c53906a5612940fdc6d026d2fcda809b3a095abbe90bcf96a19f4082a653dcf8cbc3
@@ -82,6 +82,8 @@ Thanks to everyone who has contributed to minitar:
82
82
  * Kazuyoshi Kato
83
83
  * dearblue
84
84
  * Kevin McDermott
85
+ * inkstak
86
+ * Akinori MUSHA (knu)
85
87
 
86
88
  [Minitest]: https://github.com/seattlerb/minitest
87
89
  [quality commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
data/History.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 0.8 / 2019-01-05
2
+
3
+ * inkstak resolved an issue introduced in the fix for [#31][] by allowing
4
+ spaces to be considered valid characters in strict octal handling. Octal
5
+ conversion ignores leading spaces. Merged from a slightly modified version
6
+ of PR [#35][].
7
+
8
+ * dearblue contributed PR [#32][] providing an explicit call to #bytesize for
9
+ strings that include multibyte characters. The PR has been modified to be
10
+ compatible with older versions of Ruby and extend tests.
11
+
12
+ * Akinori MUSHA (knu) contributed PR [#36][] that treats certain badly
13
+ encoded regular files (with names ending in `/`) as if they were
14
+ directories on decode.
15
+
1
16
  ## 0.7 / 2018-02-19
2
17
 
3
18
  * Fixed issue [#28][] with a modified version of PR [#29][] covering the
@@ -142,4 +157,7 @@
142
157
  [#28]: https://github.com/halostatue/minitar/issues/28
143
158
  [#29]: https://github.com/halostatue/minitar/issues/29
144
159
  [#30]: https://github.com/halostatue/minitar/issues/30
160
+ [#32]: https://github.com/halostatue/minitar/issues/32
145
161
  [#33]: https://github.com/halostatue/minitar/issues/33
162
+ [#35]: https://github.com/halostatue/minitar/issues/35
163
+ [#36]: https://github.com/halostatue/minitar/issues/36
@@ -73,7 +73,7 @@ end
73
73
  # tar.close
74
74
  # end
75
75
  module Archive::Tar::Minitar
76
- VERSION = '0.7'.freeze # :nodoc:
76
+ VERSION = '0.8'.freeze # :nodoc:
77
77
 
78
78
  # The base class for any minitar error.
79
79
  Error = Class.new(::StandardError)
@@ -279,7 +279,7 @@ module Archive::Tar::Minitar
279
279
 
280
280
  def included(mod)
281
281
  return if modules.include?(mod)
282
- warn "Including #{self} has been deprecated."
282
+ warn "Including #{self} has been deprecated (Minitar will become a class)."
283
283
  modules << mod
284
284
  end
285
285
 
@@ -288,6 +288,21 @@ module Archive::Tar::Minitar
288
288
  @modules ||= Set.new
289
289
  end
290
290
  end
291
+
292
+ # This exists to make bytesize implementations work across Ruby versions.
293
+ module ByteSize # :nodoc:
294
+ private
295
+
296
+ if ''.respond_to?(:bytesize)
297
+ def bytesize(item)
298
+ item.bytesize
299
+ end
300
+ else
301
+ def bytesize(item)
302
+ item.size
303
+ end
304
+ end
305
+ end
291
306
  end
292
307
 
293
308
  require 'archive/tar/minitar/posix_header'
@@ -123,7 +123,7 @@ class Archive::Tar::Minitar::PosixHeader
123
123
  private
124
124
 
125
125
  def strict_oct(string)
126
- return string.oct if string =~ /\A[0-7]*\z/
126
+ return string.oct if string =~ /\A[0-7 ]*\z/
127
127
  raise ArgumentError, "#{string.inspect} is not a valid octal string"
128
128
  end
129
129
  end
@@ -179,6 +179,8 @@ class Archive::Tar::Minitar::PosixHeader
179
179
 
180
180
  private
181
181
 
182
+ include Archive::Tar::Minitar::ByteSize
183
+
182
184
  def oct(num, len)
183
185
  if num.nil?
184
186
  "\0" * (len + 1)
@@ -196,7 +198,7 @@ class Archive::Tar::Minitar::PosixHeader
196
198
  oct(mtime, 11), chksum, ' ', typeflag, linkname, magic, version,
197
199
  uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix]
198
200
  str = arr.pack(HEADER_PACK_FORMAT)
199
- str + "\0" * ((BLOCK_SIZE - str.size) % BLOCK_SIZE)
201
+ str + "\0" * ((BLOCK_SIZE - bytesize(str)) % BLOCK_SIZE)
200
202
  end
201
203
 
202
204
  ##
@@ -6,6 +6,8 @@ module Archive::Tar::Minitar
6
6
  # with random access data streams.
7
7
  class Reader
8
8
  include Enumerable
9
+ include Archive::Tar::Minitar::ByteSize
10
+
9
11
  # This marks the EntryStream closed for reading without closing the
10
12
  # actual data stream.
11
13
  module InvalidEntryStream
@@ -21,6 +23,8 @@ module Archive::Tar::Minitar
21
23
 
22
24
  # EntryStreams are pseudo-streams on top of the main data stream.
23
25
  class EntryStream
26
+ include Archive::Tar::Minitar::ByteSize
27
+
24
28
  Archive::Tar::Minitar::PosixHeader::FIELDS.each do |field|
25
29
  attr_reader field.to_sym
26
30
  end
@@ -59,7 +63,7 @@ module Archive::Tar::Minitar
59
63
  len ||= @size - @read
60
64
  max_read = [len, @size - @read].min
61
65
  ret = @io.read(max_read)
62
- @read += ret.size
66
+ @read += bytesize(ret)
63
67
  ret
64
68
  end
65
69
 
@@ -74,13 +78,24 @@ module Archive::Tar::Minitar
74
78
 
75
79
  # Returns +true+ if the entry represents a directory.
76
80
  def directory?
77
- @typeflag == '5'
81
+ case @typeflag
82
+ when '5'
83
+ true
84
+ when '0', "\0"
85
+ # If the name ends with a slash, treat it as a directory.
86
+ # This is what other major tar implementations do for
87
+ # interoperability and compatibility with older tar variants
88
+ # and some new ones.
89
+ @name.end_with?('/')
90
+ else
91
+ false
92
+ end
78
93
  end
79
94
  alias directory directory?
80
95
 
81
96
  # Returns +true+ if the entry represents a plain file.
82
97
  def file?
83
- @typeflag == '0' || @typeflag == "\0"
98
+ (@typeflag == '0' || @typeflag == "\0") && !@name.end_with?('/')
84
99
  end
85
100
  alias file file?
86
101
 
@@ -233,7 +248,7 @@ module Archive::Tar::Minitar
233
248
  else
234
249
  pending = size - entry.bytes_read
235
250
  while pending > 0
236
- bread = @io.read([pending, 4096].min).size
251
+ bread = bytesize(@io.read([pending, 4096].min))
237
252
  raise UnexpectedEOF if @io.eof?
238
253
  pending -= bread
239
254
  end
@@ -3,6 +3,8 @@
3
3
  module Archive::Tar::Minitar
4
4
  # The class that writes a tar format archive to a data stream.
5
5
  class Writer
6
+ include Archive::Tar::Minitar::ByteSize
7
+
6
8
  # The exception raised when the user attempts to write more data to a
7
9
  # BoundedWriteStream than has been allocated.
8
10
  WriteBoundaryOverflow = Class.new(StandardError)
@@ -23,6 +25,8 @@ module Archive::Tar::Minitar
23
25
 
24
26
  # A WriteOnlyStream that also has a size limit.
25
27
  class BoundedWriteStream < WriteOnlyStream
28
+ include Archive::Tar::Minitar::ByteSize
29
+
26
30
  def self.const_missing(c)
27
31
  case c
28
32
  when :FileOverflow
@@ -48,10 +52,11 @@ module Archive::Tar::Minitar
48
52
  end
49
53
 
50
54
  def write(data)
51
- raise WriteBoundaryOverflow if (data.size + @written) > @limit
55
+ size = bytesize(data)
56
+ raise WriteBoundaryOverflow if (size + @written) > @limit
52
57
  @io.write(data)
53
- @written += data.size
54
- data.size
58
+ @written += size
59
+ size
55
60
  end
56
61
  end
57
62
 
@@ -153,23 +158,24 @@ module Archive::Tar::Minitar
153
158
  else
154
159
  raise ArgumentError, 'No data provided' unless data
155
160
 
156
- size = data.size if size < data.size
161
+ bytes = bytesize(data)
162
+ size = bytes if size.nil? || size < bytes
157
163
  end
158
164
 
159
165
  header[:size] = size
160
166
 
161
167
  write_header(name, header)
162
168
 
163
- os = BoundedWriteStream.new(@io, opts[:size])
169
+ os = BoundedWriteStream.new(@io, size)
164
170
  if block_given?
165
171
  yield os
166
172
  else
167
173
  os.write(data)
168
174
  end
169
175
 
170
- min_padding = opts[:size] - os.written
176
+ min_padding = size - os.written
171
177
  @io.write("\0" * min_padding)
172
- remainder = (512 - (opts[:size] % 512)) % 512
178
+ remainder = (512 - (size % 512)) % 512
173
179
  @io.write("\0" * remainder)
174
180
  end
175
181
 
@@ -286,7 +292,7 @@ module Archive::Tar::Minitar
286
292
  end
287
293
 
288
294
  def split_name(name)
289
- if name.size <= 100
295
+ if bytesize(name) <= 100
290
296
  prefix = ''
291
297
  else
292
298
  parts = name.split(/\//)
@@ -296,7 +302,7 @@ module Archive::Tar::Minitar
296
302
 
297
303
  loop do
298
304
  nxt = parts.pop || ''
299
- break if newname.size + 1 + nxt.size >= 100
305
+ break if bytesize(newname) + 1 + bytesize(nxt) >= 100
300
306
  newname = "#{nxt}/#{newname}"
301
307
  end
302
308
 
@@ -305,7 +311,7 @@ module Archive::Tar::Minitar
305
311
  name = newname
306
312
  end
307
313
 
308
- [ name, prefix, (name.size > 100 || prefix.size > 155) ]
314
+ [ name, prefix, (bytesize(name) > 100 || bytesize(prefix) > 155) ]
309
315
  end
310
316
  end
311
317
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'archive/tar/minitar'
4
4
 
5
- if defined? ::Minitar
5
+ if defined?(::Minitar) && ::Minitar != Archive::Tar::Minitar
6
6
  warn <<-EOS
7
7
  ::Minitar is already defined.
8
8
  This will conflict with future versions of minitar.
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TarTestHelpers
4
+ include Archive::Tar::Minitar::ByteSize
5
+
4
6
  Field = Struct.new(:name, :offset, :length)
5
7
  def self.Field(name, length) # rubocop:disable Style/MethodName
6
8
  @offset ||= 0
@@ -72,15 +74,25 @@ module TarTestHelpers
72
74
  end
73
75
 
74
76
  def header(type, fname, dname, length, mode)
77
+ raw_header(type,
78
+ asciiz(fname, 100),
79
+ asciiz(dname, 155),
80
+ z(to_oct(length, 11)),
81
+ z(to_oct(mode, 7))
82
+ )
83
+ end
84
+
85
+ def raw_header(type, fname, dname, length, mode)
75
86
  arr = [
76
- asciiz(fname, 100), z(to_oct(mode, 7)), z(to_oct(nil, 7)),
77
- z(to_oct(nil, 7)), z(to_oct(length, 11)), z(to_oct(0, 11)),
78
- BLANK_CHECKSUM, type, NULL_100, USTAR, DOUBLE_ZERO, asciiz('', 32),
79
- asciiz('', 32), z(to_oct(nil, 7)), z(to_oct(nil, 7)), asciiz(dname, 155)
87
+ fname, mode, z(to_oct(nil, 7)), z(to_oct(nil, 7)),
88
+ length, z(to_oct(0, 11)), BLANK_CHECKSUM, type,
89
+ NULL_100, USTAR, DOUBLE_ZERO, asciiz('', 32), asciiz('', 32),
90
+ z(to_oct(nil, 7)), z(to_oct(nil, 7)), dname
80
91
  ]
92
+
81
93
  h = arr.join.bytes.to_a.pack('C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155')
82
- ret = h + "\0" * (512 - h.size)
83
- assert_equal(512, ret.size)
94
+ ret = h + "\0" * (512 - bytesize(h))
95
+ assert_equal(512, bytesize(ret))
84
96
  ret
85
97
  end
86
98
 
@@ -100,7 +112,7 @@ module TarTestHelpers
100
112
  end
101
113
 
102
114
  def asciiz(str, length)
103
- str + "\0" * (length - str.length)
115
+ str + "\0" * (length - bytesize(str))
104
116
  end
105
117
 
106
118
  def sp(s)
@@ -80,6 +80,30 @@ class TestTarHeader < Minitest::Test
80
80
  assert(h.valid?)
81
81
  end
82
82
 
83
+ def test_from_stream_with_no_strict_octal
84
+ header = tar_file_header('a' * 100, '', 0o12345, -1213)
85
+ io = StringIO.new(header)
86
+
87
+ assert_raises(ArgumentError) do
88
+ Archive::Tar::Minitar::PosixHeader.from_stream(io)
89
+ end
90
+ end
91
+
92
+ def test_from_stream_with_octal_wrapped_by_spaces
93
+ header = raw_header(0,
94
+ asciiz('a' * 100, 100),
95
+ asciiz('', 155),
96
+ " 1213\0",
97
+ z(to_oct(0o12345, 7))
98
+ )
99
+
100
+ header = update_checksum(header)
101
+ io = StringIO.new(header)
102
+ header = Archive::Tar::Minitar::PosixHeader.from_stream(io)
103
+
104
+ assert_equal(651, header.size)
105
+ end
106
+
83
107
  def test_valid_with_invalid_header
84
108
  header = StringIO.new("testing")
85
109
  h = Archive::Tar::Minitar::PosixHeader.from_stream header
@@ -173,4 +173,47 @@ MDUzVDAwNDY0N2VQMGCgAygtLkksAjolEcjIzMOtDqgsLQ2/J0H+gNOjYBSMglEwyAEA2LchrwAGAAA=
173
173
  end
174
174
  end
175
175
  end
176
+
177
+ NON_STRICT_OCTAL_TGZ = Base64.decode64(<<-EOS).freeze
178
+ H4sIAEk55FsAA0tJLEnUK0ks0kuvYqAVMDAwMDMxUQDR5mbmYNrACMjX0zMH
179
+ AzMDUwUDIG1iZmZoYmCgYGBobGpuxqBgQDMXIYHSYqDvgU5KBDIy83CrAypL
180
+ S8NjjgEYKMDpIQLkuzkYZmdOC2Fgfnv5PleTgcjxwvXVXbaOZ3fa61/6KzHD
181
+ pENvy739mUkiKiJnJuyTbzEOuHPxvp+sXmL4E9WlJcc6FkaZh6z8srevpeRc
182
+ Zrb33fXeS3u1Wk7euf7gVqzT7CjOTMHz7+d795uePVN97P2MV15Xav/du77x
183
+ q911yx829XPfTf4v1PZndoXVlJ/fPP4fzrKdvL/q7P5VazRbzly/dHj+8/32
184
+ x/yWrLZnWnQnr+4u/zTTs/tPbT8e/jl/5n9Vm7P7k/4xwr2RsDZv7c+eGgaN
185
+ AQzKIQnSMnNSjWlsByjfm5pi5n8DGDAyQsv/RiZmxqP5nx4gJCOzWAGIQOlA
186
+ wVhPgZdroF00CkbBKBgFo2AUjIJRMApGwSgYBaNgFIyCUTAKRsEoGAWjYBSM
187
+ glEwCkbBKBgFo2AUjIJRMApIAQD0DyzXACgAAA==
188
+ EOS
189
+
190
+ def test_extract_with_non_strict_octal
191
+ reader = Zlib::GzipReader.new(StringIO.new(NON_STRICT_OCTAL_TGZ))
192
+
193
+ assert_raises(ArgumentError) do
194
+ Minitar.unpack(reader, 'data__')
195
+ end
196
+ end
197
+
198
+ OCTAL_WRAPPED_BY_SPACE_TGZ = Base64.decode64(<<-EOS).freeze
199
+ H4sIAOQg5FsAA0tJLEnUK0ks0kuvYqAVMDAwMDMxUQDR5mbmYNrACMhXgAJj
200
+ IyMFA3NzcxMzM0MTAwMFA0NjU3MzBgUDmrkICZQWA30PdFIikJGZh1sdUFla
201
+ Gh5zDMBAAU4PESDfzcEwO3NaCAPz28v3uZoMRI4Xrq/usnU8u9Ne/9JfiRkm
202
+ HXpb7u3PTBJRETkzYZ98i3HAnYv3/WT1EsOfqC4tOdaxMMo8ZOWXvX0tJecy
203
+ s73vrvde2qvVcvLO9Qe3Yp1mR3FmCp5/P9+73/Tsmepj72e88rpS++/e9Y1f
204
+ 7a5b/rCpn/tu8n+htj+zK6ym/Pzm8f9wlu3k/VVn969ao9ly5vqlw/Of77c/
205
+ 5rdktT3Tojt5dXf5p5me3X9q+/Hwz/kz/6vanN2f9I8R7o2EtXlrf/bUMGgM
206
+ YFAOSZCWmZNqTGM7QPne1BQz/xvAAEb+NzIxMx7N//QAIRmZxQpABEoHCsZ6
207
+ CrxcA+2iUTAKRsEoGAWjYBSMglEwCkbBKBgFo2AUjIJRMApGwSgYBaNgFIyC
208
+ UTAKRsEoGAWjYBSMglFACgAAuUHUvwAoAAA=
209
+ EOS
210
+
211
+ def test_extract_octal_wrapped_by_space
212
+ reader = Zlib::GzipReader.new(StringIO.new(OCTAL_WRAPPED_BY_SPACE_TGZ))
213
+ header = Archive::Tar::Minitar::PosixHeader.from_stream(reader)
214
+ assert_equal(210, header.size)
215
+
216
+ reader = Zlib::GzipReader.new(StringIO.new(OCTAL_WRAPPED_BY_SPACE_TGZ))
217
+ Minitar.unpack(reader, 'data__', [])
218
+ end
176
219
  end
@@ -4,6 +4,8 @@ require 'minitar'
4
4
  require 'minitest_helper'
5
5
 
6
6
  class TestTarReader < Minitest::Test
7
+ include Archive::Tar::Minitar::ByteSize
8
+
7
9
  def test_open_no_block
8
10
  str = tar_file_header('lib/foo', '', 0o10644, 10) + "\0" * 512
9
11
  str += tar_file_header('bar', 'baz', 0o644, 0)
@@ -21,13 +23,14 @@ class TestTarReader < Minitest::Test
21
23
  str = tar_file_header('lib/foo', '', 0o10644, 10) + "\0" * 512
22
24
  str += tar_file_header('bar', 'baz', 0o644, 0)
23
25
  str += tar_dir_header('foo', 'bar', 0o12345)
26
+ str += tar_file_header('src/', '', 0o755, 0) # "file" with a trailing slash
24
27
  str += "\0" * 1024
25
- names = %w(lib/foo bar foo)
26
- prefixes = ['', 'baz', 'bar']
27
- modes = [0o10644, 0o644, 0o12345]
28
- sizes = [10, 0, 0]
29
- isdir = [false, false, true]
30
- isfile = [true, true, false]
28
+ names = %w(lib/foo bar foo src/)
29
+ prefixes = ['', 'baz', 'bar', '']
30
+ modes = [0o10644, 0o644, 0o12345, 0o755]
31
+ sizes = [10, 0, 0, 0]
32
+ isdir = [false, false, true, true]
33
+ isfile = [true, true, false, false]
31
34
  Minitar::Reader.new(StringIO.new(str)) do |is|
32
35
  i = 0
33
36
  is.each_entry do |entry|
@@ -51,15 +54,15 @@ class TestTarReader < Minitest::Test
51
54
 
52
55
  def test_rewind_entry_works
53
56
  content = ('a'..'z').to_a.join(' ')
54
- str = tar_file_header('lib/foo', '', 0o10644, content.size) + content +
55
- "\0" * (512 - content.size)
57
+ str = tar_file_header('lib/foo', '', 0o10644, bytesize(content)) +
58
+ content + "\0" * (512 - bytesize(content))
56
59
  str << "\0" * 1024
57
60
  Minitar::Reader.new(StringIO.new(str)) do |is|
58
61
  is.each_entry do |entry|
59
62
  3.times do
60
63
  entry.rewind
61
64
  assert_equal(content, entry.read)
62
- assert_equal(content.size, entry.pos)
65
+ assert_equal(bytesize(content), entry.pos)
63
66
  end
64
67
  end
65
68
  end
@@ -67,8 +70,8 @@ class TestTarReader < Minitest::Test
67
70
 
68
71
  def test_rewind_works
69
72
  content = ('a'..'z').to_a.join(' ')
70
- str = tar_file_header('lib/foo', '', 0o10644, content.size) + content +
71
- "\0" * (512 - content.size)
73
+ str = tar_file_header('lib/foo', '', 0o10644, bytesize(content)) +
74
+ content + "\0" * (512 - bytesize(content))
72
75
  str << "\0" * 1024
73
76
  Minitar::Reader.new(StringIO.new(str)) do |is|
74
77
  3.times do
@@ -85,12 +88,12 @@ class TestTarReader < Minitest::Test
85
88
 
86
89
  def test_read_works
87
90
  contents = ('a'..'z').inject('') { |a, e| a << e * 100 }
88
- str = tar_file_header('lib/foo', '', 0o10644, contents.size) + contents
89
- str += "\0" * (512 - (str.size % 512))
91
+ str = tar_file_header('lib/foo', '', 0o10644, bytesize(contents)) + contents
92
+ str += "\0" * (512 - (bytesize(str) % 512))
90
93
  Minitar::Reader.new(StringIO.new(str)) do |is|
91
94
  is.each_entry do |entry|
92
95
  assert_kind_of(Minitar::Reader::EntryStream, entry)
93
- data = entry.read(3000) # bigger than contents.size
96
+ data = entry.read(3000) # bigger than bytesize(contents)
94
97
  assert_equal(contents, data)
95
98
  assert_equal(true, entry.eof?)
96
99
  end
@@ -99,7 +102,7 @@ class TestTarReader < Minitest::Test
99
102
  is.each_entry do |entry|
100
103
  assert_kind_of(Minitar::Reader::EntryStream, entry)
101
104
  data = entry.read(100)
102
- (entry.size - data.size).times { data << entry.getc.chr }
105
+ (entry.size - bytesize(data)).times { data << entry.getc.chr }
103
106
  assert_equal(contents, data)
104
107
  assert_equal(nil, entry.read(10))
105
108
  assert_equal(true, entry.eof?)
@@ -4,11 +4,15 @@ require 'minitar'
4
4
  require 'minitest_helper'
5
5
 
6
6
  class TestTarWriter < Minitest::Test
7
+ include Archive::Tar::Minitar::ByteSize
8
+
7
9
  class DummyIO
10
+ include Archive::Tar::Minitar::ByteSize
11
+
8
12
  attr_reader :data
9
13
 
10
14
  def initialize
11
- @data = ''
15
+ reset
12
16
  end
13
17
 
14
18
  def write(dat)
@@ -18,11 +22,14 @@ class TestTarWriter < Minitest::Test
18
22
 
19
23
  def reset
20
24
  @data = ''
25
+ @data.force_encoding('ascii-8bit') if @data.respond_to?(:force_encoding)
21
26
  end
22
27
  end
23
28
 
24
29
  def setup
25
30
  @data = 'a' * 10
31
+ @unicode = [0xc3.chr, 0xa5.chr].join * 10
32
+ @unicode.force_encoding('utf-8') if @unicode.respond_to?(:force_encoding)
26
33
  @dummyos = DummyIO.new
27
34
  @os = Minitar::Writer.new(@dummyos)
28
35
  end
@@ -146,12 +153,12 @@ class TestTarWriter < Minitest::Test
146
153
  offset = 512 * 2
147
154
  [content1, content2, ''].each do |data|
148
155
  assert_headers_equal(tar_file_header('lib/bar/baz', '', 0o644,
149
- data.size), dummyos[offset, 512])
156
+ bytesize(data)), dummyos[offset, 512])
150
157
  offset += 512
151
158
  until !data || data == ''
152
159
  chunk = data[0, 512]
153
160
  data[0, 512] = ''
154
- assert_equal(chunk + "\0" * (512 - chunk.size),
161
+ assert_equal(chunk + "\0" * (512 - bytesize(chunk)),
155
162
  dummyos[offset, 512])
156
163
  offset += 512
157
164
  end
@@ -186,7 +193,26 @@ class TestTarWriter < Minitest::Test
186
193
  f.write @data
187
194
  end
188
195
  @os.flush
189
- assert_equal(@data + ("\0" * (512 - @data.size)),
196
+ assert_equal(@data + ("\0" * (512 - bytesize(@data))),
197
+ @dummyos.data[512, 512])
198
+ end
199
+
200
+ def test_write_unicode_data
201
+ @dummyos.reset
202
+
203
+ if @unicode.respond_to?(:bytesize)
204
+ assert_equal 10, @unicode.size
205
+ assert_equal 20, @unicode.bytesize
206
+ @unicode.force_encoding('ascii-8bit')
207
+ end
208
+
209
+ file = ['lib/foo/b', 0xc3.chr, 0xa5.chr, 'r'].join
210
+
211
+ @os.add_file_simple(file, :mode => 0o644, :size => 20) do |f|
212
+ f.write @unicode
213
+ end
214
+ @os.flush
215
+ assert_equal(@unicode + ("\0" * (512 - bytesize(@unicode))),
190
216
  @dummyos.data[512, 512])
191
217
  end
192
218
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minitar
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.7'
4
+ version: '0.8'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Austin Ziegler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-28 00:00:00.000000000 Z
11
+ date: 2019-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest