minitar 0.12.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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