minitar 0.12.1 → 1.0.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/Code-of-Conduct.md +105 -51
- data/History.md +62 -51
- data/Licence.md +2 -2
- data/Manifest.txt +7 -8
- data/README.rdoc +1 -1
- data/Rakefile +3 -33
- data/lib/{archive/tar/minitar → minitar}/input.rb +24 -28
- data/lib/{archive/tar/minitar → minitar}/output.rb +10 -12
- data/lib/minitar/posix_header.rb +267 -0
- data/lib/{archive/tar/minitar → minitar}/reader.rb +18 -23
- data/lib/{archive/tar/minitar → minitar}/writer.rb +43 -49
- data/lib/minitar.rb +297 -9
- data/test/minitest_helper.rb +0 -2
- data/test/support/tar_test_helpers.rb +7 -8
- data/test/test_issue_46.rb +49 -0
- data/test/test_minitar.rb +60 -0
- data/test/test_tar_header.rb +34 -36
- data/test/test_tar_input.rb +55 -55
- data/test/test_tar_output.rb +3 -3
- data/test/test_tar_reader.rb +54 -56
- data/test/test_tar_writer.rb +37 -41
- metadata +40 -15
- data/lib/archive/tar/minitar/posix_header.rb +0 -278
- data/lib/archive/tar/minitar.rb +0 -311
- data/lib/archive-tar-minitar.rb +0 -3
- data/support/hoe/deprecated_gem.rb +0 -64
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.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Austin Ziegler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-08-
|
11
|
+
date: 2024-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -184,6 +184,34 @@ dependencies:
|
|
184
184
|
- - "~>"
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: '1.0'
|
187
|
+
- !ruby/object:Gem::Dependency
|
188
|
+
name: standard-minitest
|
189
|
+
requirement: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - "~>"
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: '1.0'
|
194
|
+
type: :development
|
195
|
+
prerelease: false
|
196
|
+
version_requirements: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - "~>"
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '1.0'
|
201
|
+
- !ruby/object:Gem::Dependency
|
202
|
+
name: standard-thread_safety
|
203
|
+
requirement: !ruby/object:Gem::Requirement
|
204
|
+
requirements:
|
205
|
+
- - "~>"
|
206
|
+
- !ruby/object:Gem::Version
|
207
|
+
version: '1.0'
|
208
|
+
type: :development
|
209
|
+
prerelease: false
|
210
|
+
version_requirements: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - "~>"
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '1.0'
|
187
215
|
- !ruby/object:Gem::Dependency
|
188
216
|
name: simplecov
|
189
217
|
requirement: !ruby/object:Gem::Requirement
|
@@ -230,17 +258,16 @@ files:
|
|
230
258
|
- Rakefile
|
231
259
|
- docs/bsdl.txt
|
232
260
|
- docs/ruby.txt
|
233
|
-
- lib/archive-tar-minitar.rb
|
234
|
-
- lib/archive/tar/minitar.rb
|
235
|
-
- lib/archive/tar/minitar/input.rb
|
236
|
-
- lib/archive/tar/minitar/output.rb
|
237
|
-
- lib/archive/tar/minitar/posix_header.rb
|
238
|
-
- lib/archive/tar/minitar/reader.rb
|
239
|
-
- lib/archive/tar/minitar/writer.rb
|
240
261
|
- lib/minitar.rb
|
241
|
-
-
|
262
|
+
- lib/minitar/input.rb
|
263
|
+
- lib/minitar/output.rb
|
264
|
+
- lib/minitar/posix_header.rb
|
265
|
+
- lib/minitar/reader.rb
|
266
|
+
- lib/minitar/writer.rb
|
242
267
|
- test/minitest_helper.rb
|
243
268
|
- test/support/tar_test_helpers.rb
|
269
|
+
- test/test_issue_46.rb
|
270
|
+
- test/test_minitar.rb
|
244
271
|
- test/test_tar_header.rb
|
245
272
|
- test/test_tar_input.rb
|
246
273
|
- test/test_tar_output.rb
|
@@ -255,9 +282,7 @@ metadata:
|
|
255
282
|
source_code_uri: https://github.com/halostatue/minitar/
|
256
283
|
bug_tracker_uri: https://github.com/halostatue/minitar/issues
|
257
284
|
rubygems_mfa_required: 'true'
|
258
|
-
post_install_message:
|
259
|
-
The `minitar` executable is no longer bundled with `minitar`. If you are
|
260
|
-
expecting this executable, make sure you also install `minitar-cli`.
|
285
|
+
post_install_message:
|
261
286
|
rdoc_options:
|
262
287
|
- "--main"
|
263
288
|
- README.rdoc
|
@@ -267,14 +292,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
267
292
|
requirements:
|
268
293
|
- - ">="
|
269
294
|
- !ruby/object:Gem::Version
|
270
|
-
version: '1
|
295
|
+
version: '3.1'
|
271
296
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
272
297
|
requirements:
|
273
298
|
- - ">="
|
274
299
|
- !ruby/object:Gem::Version
|
275
300
|
version: '0'
|
276
301
|
requirements: []
|
277
|
-
rubygems_version: 3.
|
302
|
+
rubygems_version: 3.4.19
|
278
303
|
signing_key:
|
279
304
|
specification_version: 4
|
280
305
|
summary: The minitar library is a pure-Ruby library that provides the ability to deal
|
@@ -1,278 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
##
|
4
|
-
module Archive; end
|
5
|
-
|
6
|
-
##
|
7
|
-
module Archive::Tar; end
|
8
|
-
|
9
|
-
##
|
10
|
-
module Archive::Tar::Minitar; end
|
11
|
-
|
12
|
-
# Implements the POSIX tar header as a Ruby class. The structure of
|
13
|
-
# the POSIX tar header is:
|
14
|
-
#
|
15
|
-
# struct tarfile_entry_posix
|
16
|
-
# { // pack/unpack
|
17
|
-
# char name[100]; // ASCII (+ Z unless filled) a100/Z100
|
18
|
-
# char mode[8]; // 0 padded, octal, null a8 /A8
|
19
|
-
# char uid[8]; // 0 padded, octal, null a8 /A8
|
20
|
-
# char gid[8]; // 0 padded, octal, null a8 /A8
|
21
|
-
# char size[12]; // 0 padded, octal, null a12 /A12
|
22
|
-
# char mtime[12]; // 0 padded, octal, null a12 /A12
|
23
|
-
# char checksum[8]; // 0 padded, octal, null, space a8 /A8
|
24
|
-
# char typeflag[1]; // see below a /a
|
25
|
-
# char linkname[100]; // ASCII + (Z unless filled) a100/Z100
|
26
|
-
# char magic[6]; // "ustar\0" a6 /A6
|
27
|
-
# char version[2]; // "00" a2 /A2
|
28
|
-
# char uname[32]; // ASCIIZ a32 /Z32
|
29
|
-
# char gname[32]; // ASCIIZ a32 /Z32
|
30
|
-
# char devmajor[8]; // 0 padded, octal, null a8 /A8
|
31
|
-
# char devminor[8]; // 0 padded, octal, null a8 /A8
|
32
|
-
# char prefix[155]; // ASCII (+ Z unless filled) a155/Z155
|
33
|
-
# };
|
34
|
-
#
|
35
|
-
# The #typeflag is one of several known values.
|
36
|
-
#
|
37
|
-
# POSIX indicates that "A POSIX-compliant implementation must treat any
|
38
|
-
# unrecognized typeflag value as a regular file."
|
39
|
-
class Archive::Tar::Minitar::PosixHeader
|
40
|
-
BLOCK_SIZE = 512
|
41
|
-
MAGIC_BYTES = "ustar".freeze
|
42
|
-
|
43
|
-
GNU_EXT_LONG_LINK = "././@LongLink"
|
44
|
-
|
45
|
-
# Fields that must be set in a POSIX tar(1) header.
|
46
|
-
REQUIRED_FIELDS = [:name, :size, :prefix, :mode].freeze
|
47
|
-
# Fields that may be set in a POSIX tar(1) header.
|
48
|
-
OPTIONAL_FIELDS = [
|
49
|
-
:uid, :gid, :mtime, :checksum, :typeflag, :linkname, :magic, :version,
|
50
|
-
:uname, :gname, :devmajor, :devminor
|
51
|
-
].freeze
|
52
|
-
|
53
|
-
# All fields available in a POSIX tar(1) header.
|
54
|
-
FIELDS = (REQUIRED_FIELDS + OPTIONAL_FIELDS).freeze
|
55
|
-
|
56
|
-
FIELDS.each do |f|
|
57
|
-
attr_reader f.to_sym unless f.to_sym == :name
|
58
|
-
end
|
59
|
-
|
60
|
-
# The name of the file. By default, limited to 100 bytes. Required. May be
|
61
|
-
# longer (up to BLOCK_SIZE bytes) if using the GNU long name tar extension.
|
62
|
-
attr_accessor :name
|
63
|
-
|
64
|
-
# The pack format passed to Array#pack for encoding a header.
|
65
|
-
HEADER_PACK_FORMAT = "a100a8a8a8a12a12a7aaa100a6a2a32a32a8a8a155".freeze
|
66
|
-
# The unpack format passed to String#unpack for decoding a header.
|
67
|
-
HEADER_UNPACK_FORMAT = "Z100A8A8A8A12A12A8aZ100A6A2Z32Z32A8A8Z155".freeze
|
68
|
-
|
69
|
-
class << self
|
70
|
-
# Creates a new PosixHeader from a data stream.
|
71
|
-
def from_stream(stream)
|
72
|
-
from_data(stream.read(BLOCK_SIZE))
|
73
|
-
end
|
74
|
-
|
75
|
-
# Creates a new PosixHeader from a data stream. Deprecated; use
|
76
|
-
# PosixHeader.from_stream instead.
|
77
|
-
def new_from_stream(stream)
|
78
|
-
warn "#{__method__} has been deprecated; use from_stream instead."
|
79
|
-
from_stream(stream)
|
80
|
-
end
|
81
|
-
|
82
|
-
# Creates a new PosixHeader from a BLOCK_SIZE-byte data buffer.
|
83
|
-
def from_data(data)
|
84
|
-
fields = data.unpack(HEADER_UNPACK_FORMAT)
|
85
|
-
name = fields.shift
|
86
|
-
mode = fields.shift.oct
|
87
|
-
uid = fields.shift.oct
|
88
|
-
gid = fields.shift.oct
|
89
|
-
size = strict_oct(fields.shift)
|
90
|
-
mtime = fields.shift.oct
|
91
|
-
checksum = fields.shift.oct
|
92
|
-
typeflag = fields.shift
|
93
|
-
linkname = fields.shift
|
94
|
-
magic = fields.shift
|
95
|
-
version = fields.shift.oct
|
96
|
-
uname = fields.shift
|
97
|
-
gname = fields.shift
|
98
|
-
devmajor = fields.shift.oct
|
99
|
-
devminor = fields.shift.oct
|
100
|
-
prefix = fields.shift
|
101
|
-
|
102
|
-
empty = !data.each_byte.any?(&:nonzero?)
|
103
|
-
|
104
|
-
new(
|
105
|
-
:name => name,
|
106
|
-
:mode => mode,
|
107
|
-
:uid => uid,
|
108
|
-
:gid => gid,
|
109
|
-
:size => size,
|
110
|
-
:mtime => mtime,
|
111
|
-
:checksum => checksum,
|
112
|
-
:typeflag => typeflag,
|
113
|
-
:magic => magic,
|
114
|
-
:version => version,
|
115
|
-
:uname => uname,
|
116
|
-
:gname => gname,
|
117
|
-
:devmajor => devmajor,
|
118
|
-
:devminor => devminor,
|
119
|
-
:prefix => prefix,
|
120
|
-
:empty => empty,
|
121
|
-
:linkname => linkname
|
122
|
-
)
|
123
|
-
end
|
124
|
-
|
125
|
-
private
|
126
|
-
|
127
|
-
def strict_oct(string)
|
128
|
-
return string.oct if string =~ /\A[0-7 ]*\z/
|
129
|
-
raise ArgumentError, "#{string.inspect} is not a valid octal string"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# Creates a new PosixHeader. A PosixHeader cannot be created unless
|
134
|
-
# +name+, +size+, +prefix+, and +mode+ are provided.
|
135
|
-
def initialize(v)
|
136
|
-
REQUIRED_FIELDS.each do |f|
|
137
|
-
raise ArgumentError, "Field #{f} is required." unless v.key?(f)
|
138
|
-
end
|
139
|
-
|
140
|
-
v[:mtime] = v[:mtime].to_i
|
141
|
-
v[:checksum] ||= ""
|
142
|
-
v[:typeflag] ||= "0"
|
143
|
-
v[:magic] ||= MAGIC_BYTES
|
144
|
-
v[:version] ||= "00"
|
145
|
-
|
146
|
-
FIELDS.each do |f|
|
147
|
-
instance_variable_set(:"@#{f}", v[f])
|
148
|
-
end
|
149
|
-
|
150
|
-
@empty = v[:empty]
|
151
|
-
end
|
152
|
-
|
153
|
-
# Indicates if the header was an empty header.
|
154
|
-
def empty?
|
155
|
-
@empty
|
156
|
-
end
|
157
|
-
|
158
|
-
# Indicates if the header has a valid magic value.
|
159
|
-
def valid?
|
160
|
-
empty? || @magic == MAGIC_BYTES
|
161
|
-
end
|
162
|
-
|
163
|
-
# Returns +true+ if the header is a long name special header which indicates
|
164
|
-
# that the next block of data is the filename.
|
165
|
-
def long_name?
|
166
|
-
typeflag == "L" && name == GNU_EXT_LONG_LINK
|
167
|
-
end
|
168
|
-
|
169
|
-
# A string representation of the header.
|
170
|
-
def to_s
|
171
|
-
update_checksum
|
172
|
-
header(@checksum)
|
173
|
-
end
|
174
|
-
alias_method :to_str, :to_s
|
175
|
-
|
176
|
-
# Update the checksum field.
|
177
|
-
def update_checksum
|
178
|
-
hh = header(" " * 8)
|
179
|
-
@checksum = oct(calculate_checksum(hh), 6)
|
180
|
-
end
|
181
|
-
|
182
|
-
private
|
183
|
-
|
184
|
-
include Archive::Tar::Minitar::ByteSize
|
185
|
-
|
186
|
-
def oct(num, len)
|
187
|
-
if num.nil?
|
188
|
-
"\0" * (len + 1)
|
189
|
-
else
|
190
|
-
"%0#{len}o" % num
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def calculate_checksum(hdr)
|
195
|
-
hdr.unpack("C*").inject { |a, e| a + e }
|
196
|
-
end
|
197
|
-
|
198
|
-
def header(chksum)
|
199
|
-
arr = [name, oct(mode, 7), oct(uid, 7), oct(gid, 7), oct(size, 11),
|
200
|
-
oct(mtime, 11), chksum, " ", typeflag, linkname, magic, version,
|
201
|
-
uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix]
|
202
|
-
str = arr.pack(HEADER_PACK_FORMAT)
|
203
|
-
str + "\0" * ((BLOCK_SIZE - bytesize(str)) % BLOCK_SIZE)
|
204
|
-
end
|
205
|
-
|
206
|
-
##
|
207
|
-
# :attr_reader: size
|
208
|
-
# The size of the file. Required.
|
209
|
-
|
210
|
-
##
|
211
|
-
# :attr_reader: prefix
|
212
|
-
# The prefix of the file; the path before #name. Limited to 155 bytes.
|
213
|
-
# Required.
|
214
|
-
|
215
|
-
##
|
216
|
-
# :attr_reader: mode
|
217
|
-
# The Unix file mode of the file. Stored as an octal integer. Required.
|
218
|
-
|
219
|
-
##
|
220
|
-
# :attr_reader: uid
|
221
|
-
# The Unix owner user ID of the file. Stored as an octal integer.
|
222
|
-
|
223
|
-
##
|
224
|
-
# :attr_reader: uname
|
225
|
-
# The user name of the Unix owner of the file.
|
226
|
-
|
227
|
-
##
|
228
|
-
# :attr_reader: gid
|
229
|
-
# The Unix owner group ID of the file. Stored as an octal integer.
|
230
|
-
|
231
|
-
##
|
232
|
-
# :attr_reader: gname
|
233
|
-
# The group name of the Unix owner of the file.
|
234
|
-
|
235
|
-
##
|
236
|
-
# :attr_reader: mtime
|
237
|
-
# The modification time of the file in epoch seconds. Stored as an
|
238
|
-
# octal integer.
|
239
|
-
|
240
|
-
##
|
241
|
-
# :attr_reader: checksum
|
242
|
-
# The checksum of the file. Stored as an octal integer. Calculated
|
243
|
-
# before encoding the header as a string.
|
244
|
-
|
245
|
-
##
|
246
|
-
# :attr_reader: typeflag
|
247
|
-
# The type of record in the file.
|
248
|
-
#
|
249
|
-
# +0+:: Regular file. NULL should be treated as a synonym, for compatibility
|
250
|
-
# purposes.
|
251
|
-
# +1+:: Hard link.
|
252
|
-
# +2+:: Symbolic link.
|
253
|
-
# +3+:: Character device node.
|
254
|
-
# +4+:: Block device node.
|
255
|
-
# +5+:: Directory.
|
256
|
-
# +6+:: FIFO node.
|
257
|
-
# +7+:: Reserved.
|
258
|
-
|
259
|
-
##
|
260
|
-
# :attr_reader: linkname
|
261
|
-
# The name of the link stored. Not currently used.
|
262
|
-
|
263
|
-
##
|
264
|
-
# :attr_reader: magic
|
265
|
-
# Always "ustar\0".
|
266
|
-
|
267
|
-
##
|
268
|
-
# :attr_reader: version
|
269
|
-
# Always "00"
|
270
|
-
|
271
|
-
##
|
272
|
-
# :attr_reader: devmajor
|
273
|
-
# The major device ID. Not currently used.
|
274
|
-
|
275
|
-
##
|
276
|
-
# :attr_reader: devminor
|
277
|
-
# The minor device ID. Not currently used.
|
278
|
-
end
|
data/lib/archive/tar/minitar.rb
DELETED
@@ -1,311 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
##
|
4
|
-
module Archive; end
|
5
|
-
|
6
|
-
##
|
7
|
-
module Archive::Tar; end
|
8
|
-
|
9
|
-
require "fileutils"
|
10
|
-
require "rbconfig"
|
11
|
-
|
12
|
-
class << Archive::Tar # :nodoc:
|
13
|
-
def const_missing(const) # :nodoc:
|
14
|
-
case const
|
15
|
-
when :PosixHeader
|
16
|
-
warn "Archive::Tar::PosixHeader has been renamed to " \
|
17
|
-
"Archive::Tar::Minitar::PosixHeader"
|
18
|
-
const_set :PosixHeader, Archive::Tar::Minitar::PosixHeader
|
19
|
-
else
|
20
|
-
super
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def included(mod)
|
27
|
-
return if modules.include?(mod)
|
28
|
-
warn "Including Minitar via the #{self} namespace is deprecated."
|
29
|
-
modules.add mod
|
30
|
-
end
|
31
|
-
|
32
|
-
def modules
|
33
|
-
require "set"
|
34
|
-
@modules ||= Set.new
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# == Synopsis
|
39
|
-
#
|
40
|
-
# Using minitar is easy. The simplest case is:
|
41
|
-
#
|
42
|
-
# require 'zlib'
|
43
|
-
# require 'minitar'
|
44
|
-
#
|
45
|
-
# # Packs everything that matches Find.find('tests').
|
46
|
-
# # test.tar will automatically be closed by Minitar.pack.
|
47
|
-
# Minitar.pack('tests', File.open('test.tar', 'wb'))
|
48
|
-
#
|
49
|
-
# # Unpacks 'test.tar' to 'x', creating 'x' if necessary.
|
50
|
-
# Minitar.unpack('test.tar', 'x')
|
51
|
-
#
|
52
|
-
# A gzipped tar can be written with:
|
53
|
-
#
|
54
|
-
# # test.tgz will be closed automatically.
|
55
|
-
# Minitar.pack('tests', Zlib::GzipWriter.new(File.open('test.tgz', 'wb'))
|
56
|
-
#
|
57
|
-
# # test.tgz will be closed automatically.
|
58
|
-
# Minitar.unpack(Zlib::GzipReader.new(File.open('test.tgz', 'rb')), 'x')
|
59
|
-
#
|
60
|
-
# As the case above shows, one need not write to a file. However, it will
|
61
|
-
# sometimes require that one dive a little deeper into the API, as in the case
|
62
|
-
# of StringIO objects. Note that I'm not providing a block with
|
63
|
-
# Minitar::Output, as Minitar::Output#close automatically closes both the
|
64
|
-
# Output object and the wrapped data stream object.
|
65
|
-
#
|
66
|
-
# begin
|
67
|
-
# sgz = Zlib::GzipWriter.new(StringIO.new(""))
|
68
|
-
# tar = Output.new(sgz)
|
69
|
-
# Find.find('tests') do |entry|
|
70
|
-
# Minitar.pack_file(entry, tar)
|
71
|
-
# end
|
72
|
-
# ensure
|
73
|
-
# # Closes both tar and sgz.
|
74
|
-
# tar.close
|
75
|
-
# end
|
76
|
-
module Archive::Tar::Minitar
|
77
|
-
VERSION = "0.12.1".freeze # :nodoc:
|
78
|
-
|
79
|
-
# The base class for any minitar error.
|
80
|
-
Error = Class.new(::StandardError)
|
81
|
-
# Raised when a wrapped data stream class is not seekable.
|
82
|
-
NonSeekableStream = Class.new(Error)
|
83
|
-
# The exception raised when operations are performed on a stream that has
|
84
|
-
# previously been closed.
|
85
|
-
ClosedStream = Class.new(Error)
|
86
|
-
# The exception raised when a filename exceeds 256 bytes in length, the
|
87
|
-
# maximum supported by the standard Tar format.
|
88
|
-
FileNameTooLong = Class.new(Error)
|
89
|
-
# The exception raised when a data stream ends before the amount of data
|
90
|
-
# expected in the archive's PosixHeader.
|
91
|
-
UnexpectedEOF = Class.new(StandardError)
|
92
|
-
# The exception raised when a file contains a relative path in secure mode
|
93
|
-
# (the default for this version).
|
94
|
-
SecureRelativePathError = Class.new(Error)
|
95
|
-
# The exception raised when a file contains an invalid Posix header.
|
96
|
-
InvalidTarStream = Class.new(Error)
|
97
|
-
|
98
|
-
class << self
|
99
|
-
# Tests if +path+ refers to a directory. Fixes an apparently
|
100
|
-
# corrupted <tt>stat()</tt> call on Windows.
|
101
|
-
def dir?(path)
|
102
|
-
# rubocop:disable Style/CharacterLiteral
|
103
|
-
File.directory?((path[-1] == ?/) ? path : "#{path}/")
|
104
|
-
# rubocop:enable Style/CharacterLiteral
|
105
|
-
end
|
106
|
-
|
107
|
-
# A convenience method for wrapping Archive::Tar::Minitar::Input.open
|
108
|
-
# (mode +r+) and Archive::Tar::Minitar::Output.open (mode +w+). No other
|
109
|
-
# modes are currently supported.
|
110
|
-
def open(dest, mode = "r", &block)
|
111
|
-
case mode
|
112
|
-
when "r"
|
113
|
-
Input.open(dest, &block)
|
114
|
-
when "w"
|
115
|
-
Output.open(dest, &block)
|
116
|
-
else
|
117
|
-
raise "Unknown open mode for Archive::Tar::Minitar.open."
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def const_missing(c) # :nodoc:
|
122
|
-
case c
|
123
|
-
when :BlockRequired
|
124
|
-
warn "This constant has been removed."
|
125
|
-
const_set(:BlockRequired, Class.new(StandardError))
|
126
|
-
else
|
127
|
-
super
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def windows? # :nodoc:
|
132
|
-
RbConfig::CONFIG["host_os"] =~ /^(mswin|mingw|cygwin)/
|
133
|
-
end
|
134
|
-
|
135
|
-
# A convenience method to pack the file provided. +entry+ may either be a
|
136
|
-
# filename (in which case various values for the file (see below) will be
|
137
|
-
# obtained from <tt>File#stat(entry)</tt> or a Hash with the fields:
|
138
|
-
#
|
139
|
-
# <tt>:name</tt>:: The filename to be packed into the archive. Required.
|
140
|
-
# <tt>:mode</tt>:: The mode to be applied.
|
141
|
-
# <tt>:uid</tt>:: The user owner of the file. (Ignored on Windows.)
|
142
|
-
# <tt>:gid</tt>:: The group owner of the file. (Ignored on Windows.)
|
143
|
-
# <tt>:mtime</tt>:: The modification Time of the file.
|
144
|
-
#
|
145
|
-
# During packing, if a block is provided, #pack_file yields an +action+
|
146
|
-
# Symol, the full name of the file being packed, and a Hash of
|
147
|
-
# statistical information, just as with
|
148
|
-
# Archive::Tar::Minitar::Input#extract_entry.
|
149
|
-
#
|
150
|
-
# The +action+ will be one of:
|
151
|
-
# <tt>:dir</tt>:: The +entry+ is a directory.
|
152
|
-
# <tt>:file_start</tt>:: The +entry+ is a file; the extract of the
|
153
|
-
# file is just beginning.
|
154
|
-
# <tt>:file_progress</tt>:: Yielded every 4096 bytes during the extract
|
155
|
-
# of the +entry+.
|
156
|
-
# <tt>:file_done</tt>:: Yielded when the +entry+ is completed.
|
157
|
-
#
|
158
|
-
# The +stats+ hash contains the following keys:
|
159
|
-
# <tt>:current</tt>:: The current total number of bytes read in the
|
160
|
-
# +entry+.
|
161
|
-
# <tt>:currinc</tt>:: The current number of bytes read in this read
|
162
|
-
# cycle.
|
163
|
-
# <tt>:name</tt>:: The filename to be packed into the tarchive.
|
164
|
-
# *REQUIRED*.
|
165
|
-
# <tt>:mode</tt>:: The mode to be applied.
|
166
|
-
# <tt>:uid</tt>:: The user owner of the file. (+nil+ on Windows.)
|
167
|
-
# <tt>:gid</tt>:: The group owner of the file. (+nil+ on Windows.)
|
168
|
-
# <tt>:mtime</tt>:: The modification Time of the file.
|
169
|
-
def pack_file(entry, outputter) # :yields action, name, stats:
|
170
|
-
if outputter.is_a?(Archive::Tar::Minitar::Output)
|
171
|
-
outputter = outputter.tar
|
172
|
-
end
|
173
|
-
|
174
|
-
stats = {}
|
175
|
-
|
176
|
-
if entry.is_a?(Hash)
|
177
|
-
name = entry[:name]
|
178
|
-
entry.each { |kk, vv| stats[kk] = vv unless vv.nil? }
|
179
|
-
else
|
180
|
-
name = entry
|
181
|
-
end
|
182
|
-
|
183
|
-
name = name.sub(%r{\./}, "")
|
184
|
-
stat = File.stat(name)
|
185
|
-
stats[:mode] ||= stat.mode
|
186
|
-
stats[:mtime] ||= stat.mtime
|
187
|
-
stats[:size] = stat.size
|
188
|
-
|
189
|
-
if windows?
|
190
|
-
stats[:uid] = nil
|
191
|
-
stats[:gid] = nil
|
192
|
-
else
|
193
|
-
stats[:uid] ||= stat.uid
|
194
|
-
stats[:gid] ||= stat.gid
|
195
|
-
end
|
196
|
-
|
197
|
-
if File.file?(name)
|
198
|
-
outputter.add_file_simple(name, stats) do |os|
|
199
|
-
stats[:current] = 0
|
200
|
-
yield :file_start, name, stats if block_given?
|
201
|
-
File.open(name, "rb") do |ff|
|
202
|
-
until ff.eof?
|
203
|
-
stats[:currinc] = os.write(ff.read(4096))
|
204
|
-
stats[:current] += stats[:currinc]
|
205
|
-
yield :file_progress, name, stats if block_given?
|
206
|
-
end
|
207
|
-
end
|
208
|
-
yield :file_done, name, stats if block_given?
|
209
|
-
end
|
210
|
-
elsif dir?(name)
|
211
|
-
yield :dir, name, stats if block_given?
|
212
|
-
outputter.mkdir(name, stats)
|
213
|
-
else
|
214
|
-
raise "Don't yet know how to pack this type of file."
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
# A convenience method to pack files specified by +src+ into +dest+. If
|
219
|
-
# +src+ is an Array, then each file detailed therein will be packed into
|
220
|
-
# the resulting Archive::Tar::Minitar::Output stream; if +recurse_dirs+ is
|
221
|
-
# true, then directories will be recursed.
|
222
|
-
#
|
223
|
-
# If +src+ is not an Array, it will be treated as the result of Find.find;
|
224
|
-
# all files matching will be packed.
|
225
|
-
def pack(src, dest, recurse_dirs = true, &block)
|
226
|
-
require "find"
|
227
|
-
Output.open(dest) do |outp|
|
228
|
-
if src.is_a?(Array)
|
229
|
-
src.each do |entry|
|
230
|
-
if dir?(entry) && recurse_dirs
|
231
|
-
Find.find(entry) do |ee|
|
232
|
-
pack_file(ee, outp, &block)
|
233
|
-
end
|
234
|
-
else
|
235
|
-
pack_file(entry, outp, &block)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
else
|
239
|
-
Find.find(src) do |entry|
|
240
|
-
pack_file(entry, outp, &block)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
# A convenience method to unpack files from +src+ into the directory
|
247
|
-
# specified by +dest+. Only those files named explicitly in +files+
|
248
|
-
# will be extracted.
|
249
|
-
def unpack(src, dest, files = [], options = {}, &block)
|
250
|
-
Input.open(src) do |inp|
|
251
|
-
if File.exist?(dest) && !dir?(dest)
|
252
|
-
raise "Can't unpack to a non-directory."
|
253
|
-
end
|
254
|
-
|
255
|
-
FileUtils.mkdir_p(dest) unless File.exist?(dest)
|
256
|
-
|
257
|
-
inp.each do |entry|
|
258
|
-
if files.empty? || files.include?(entry.full_name)
|
259
|
-
inp.extract_entry(dest, entry, options, &block)
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
# Check whether +io+ can seek without errors.
|
266
|
-
def seekable?(io, methods = nil)
|
267
|
-
# The IO class throws an exception at runtime if we try to change
|
268
|
-
# position on a non-regular file.
|
269
|
-
if io.respond_to?(:stat)
|
270
|
-
io.stat.file?
|
271
|
-
else
|
272
|
-
# Duck-type the rest of this.
|
273
|
-
methods ||= [:pos, :pos=, :seek, :rewind]
|
274
|
-
methods = [methods] unless methods.is_a?(Array)
|
275
|
-
methods.all? { |m| io.respond_to?(m) }
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
private
|
280
|
-
|
281
|
-
def included(mod)
|
282
|
-
return if modules.include?(mod)
|
283
|
-
warn "Including #{self} has been deprecated (Minitar will become a class)."
|
284
|
-
modules << mod
|
285
|
-
end
|
286
|
-
|
287
|
-
def modules
|
288
|
-
require "set"
|
289
|
-
@modules ||= Set.new
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
# This exists to make bytesize implementations work across Ruby versions.
|
294
|
-
module ByteSize # :nodoc:
|
295
|
-
private
|
296
|
-
|
297
|
-
if "".respond_to?(:bytesize)
|
298
|
-
def bytesize(item)
|
299
|
-
item.bytesize
|
300
|
-
end
|
301
|
-
else
|
302
|
-
def bytesize(item)
|
303
|
-
item.size
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
require "archive/tar/minitar/posix_header"
|
310
|
-
require "archive/tar/minitar/input"
|
311
|
-
require "archive/tar/minitar/output"
|
data/lib/archive-tar-minitar.rb
DELETED