mini_tarball 0.3.0 → 0.3.1
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/lib/mini_tarball/header.rb +37 -4
- data/lib/mini_tarball/header_fields.rb +50 -0
- data/lib/mini_tarball/header_formatter.rb +31 -18
- data/lib/mini_tarball/header_writer.rb +7 -69
- data/lib/mini_tarball/streams/limited_size_stream.rb +8 -3
- data/lib/mini_tarball/streams/placeholder_stream.rb +4 -1
- data/lib/mini_tarball/version.rb +1 -1
- data/lib/mini_tarball/writer.rb +91 -46
- data/lib/mini_tarball.rb +9 -8
- metadata +33 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 313b7544e163106d7c251eb36ace29a96c22dfe43bc198310966155c18417260
|
4
|
+
data.tar.gz: fe252395b2daa1b7a8843ff27a0f6b87d96dff09031c485c42c217ad39b9ba52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acf0381c3b1dfc12c7d3e2da19f3bf3747f3c60e4af2939718d0095fe6dbff6554bf359beaf8e2a74b2a6f44b317620eb85977360a6bce0cae88c638442b5e86
|
7
|
+
data.tar.gz: f86d7def07d9c89a5375f2428324c1b9e8f7ec2e35c57d473c35a79e42207929685410900e2e76e1e19969ac2051f3f34e9f8f2669de792c2a522a6da78e1c56
|
data/lib/mini_tarball/header.rb
CHANGED
@@ -8,7 +8,7 @@ module MiniTarball
|
|
8
8
|
TYPE_REGULAR = "0"
|
9
9
|
TYPE_LONG_LINK = "L"
|
10
10
|
|
11
|
-
#
|
11
|
+
# stree-ignore
|
12
12
|
FIELDS = {
|
13
13
|
name: { length: 100, type: :chars },
|
14
14
|
mode: { length: 8, type: :mode },
|
@@ -27,9 +27,33 @@ module MiniTarball
|
|
27
27
|
devminor: { length: 8, type: :number },
|
28
28
|
prefix: { length: 155, type: :chars }
|
29
29
|
}
|
30
|
-
# rubocop:enable Layout/HashAlignment
|
31
30
|
|
32
|
-
def
|
31
|
+
def self.long_link_header(name)
|
32
|
+
Header.new(
|
33
|
+
name: "././@LongLink",
|
34
|
+
mode: 0644,
|
35
|
+
uid: 0,
|
36
|
+
gid: 0,
|
37
|
+
size: name.bytesize + 1,
|
38
|
+
typeflag: TYPE_LONG_LINK,
|
39
|
+
uname: "root",
|
40
|
+
gname: "root",
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
# :reek:LongParameterList
|
45
|
+
def initialize(
|
46
|
+
name:,
|
47
|
+
mode: 0,
|
48
|
+
uid: nil,
|
49
|
+
gid: nil,
|
50
|
+
size: 0,
|
51
|
+
mtime: 0,
|
52
|
+
typeflag: TYPE_REGULAR,
|
53
|
+
linkname: "",
|
54
|
+
uname: nil,
|
55
|
+
gname: nil
|
56
|
+
)
|
33
57
|
@values = {
|
34
58
|
name: name,
|
35
59
|
mode: mode,
|
@@ -46,12 +70,21 @@ module MiniTarball
|
|
46
70
|
gname: gname,
|
47
71
|
devmajor: nil,
|
48
72
|
devminor: nil,
|
49
|
-
prefix: ""
|
73
|
+
prefix: "",
|
50
74
|
}
|
51
75
|
end
|
52
76
|
|
53
77
|
def value_of(key)
|
54
78
|
@values[key]
|
55
79
|
end
|
80
|
+
|
81
|
+
def to_binary
|
82
|
+
fields = HeaderFields.new(self)
|
83
|
+
fields.to_binary
|
84
|
+
end
|
85
|
+
|
86
|
+
def has_long_name?
|
87
|
+
value_of(:name).bytesize > FIELDS[:name][:length]
|
88
|
+
end
|
56
89
|
end
|
57
90
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MiniTarball
|
4
|
+
class HeaderFields
|
5
|
+
def self.pack_format
|
6
|
+
@pack_format ||= Header::FIELDS.values.map { |field| "a#{field[:length]}" }.join("")
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(header)
|
10
|
+
@header = header
|
11
|
+
@values_by_field = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_binary
|
15
|
+
Header::FIELDS.each_key do |name|
|
16
|
+
value = @header.value_of(name)
|
17
|
+
set_value(name, value)
|
18
|
+
end
|
19
|
+
|
20
|
+
update_checksum
|
21
|
+
HeaderFormatter.zero_pad(encode_fields)
|
22
|
+
end
|
23
|
+
|
24
|
+
# :reek:DuplicateMethodCall
|
25
|
+
def set_value(name, value)
|
26
|
+
field = Header::FIELDS[name]
|
27
|
+
|
28
|
+
case field[:type]
|
29
|
+
when :number
|
30
|
+
@values_by_field[name] = HeaderFormatter.format_number(value, field[:length])
|
31
|
+
when :mode
|
32
|
+
@values_by_field[name] = HeaderFormatter.format_permissions(value, field[:length])
|
33
|
+
when :checksum
|
34
|
+
@values_by_field[name] = HeaderFormatter.format_checksum(value)
|
35
|
+
else
|
36
|
+
@values_by_field[name] = value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_checksum
|
41
|
+
checksum = encode_fields.unpack("C*").sum
|
42
|
+
set_value(:checksum, checksum)
|
43
|
+
end
|
44
|
+
|
45
|
+
private def encode_fields
|
46
|
+
values = @values_by_field.values
|
47
|
+
values.pack(HeaderFields.pack_format)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -3,30 +3,50 @@
|
|
3
3
|
module MiniTarball
|
4
4
|
ValueTooLargeError = Class.new(StandardError)
|
5
5
|
|
6
|
-
|
6
|
+
module HeaderFormatter
|
7
7
|
PERMISSION_BITMASK = 0007777
|
8
8
|
|
9
9
|
# @param value [Integer]
|
10
10
|
# @param length [Integer]
|
11
11
|
def self.format_number(value, length)
|
12
|
-
return nil if value
|
12
|
+
return nil if !value
|
13
13
|
raise NotImplementedError.new("Negative numbers are not supported") if value.negative?
|
14
14
|
|
15
|
+
fits_into_octal?(value, length) ? to_octal(value, length) : to_base256(value, length)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Removes file type bitfields and returns file permissions as formatted number
|
19
|
+
# @param value [Integer]
|
20
|
+
# @param length [Integer]
|
21
|
+
def self.format_permissions(value, length)
|
22
|
+
format_number(value & PERMISSION_BITMASK, length)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.format_checksum(checksum)
|
26
|
+
length = Header::FIELDS[:checksum][:length]
|
27
|
+
|
28
|
+
checksum ? format_number(checksum, length - 1) << "\0 " : " " * length
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.zero_pad(binary)
|
32
|
+
padding_length = (Header::BLOCK_SIZE - binary.length) % Header::BLOCK_SIZE
|
33
|
+
binary << "\0" * padding_length
|
34
|
+
end
|
35
|
+
|
36
|
+
private_class_method def self.fits_into_octal?(value, length)
|
15
37
|
octal_length = length - 1
|
16
38
|
max_octal_value = ("0" + "7" * octal_length).to_i(8)
|
17
|
-
|
18
|
-
if (value <= max_octal_value)
|
19
|
-
to_octal(value, octal_length)
|
20
|
-
else
|
21
|
-
to_base256(value, length)
|
22
|
-
end
|
39
|
+
value <= max_octal_value
|
23
40
|
end
|
24
41
|
|
25
|
-
def self.to_octal(value, length)
|
26
|
-
|
42
|
+
private_class_method def self.to_octal(value, length)
|
43
|
+
octal_length = length - 1
|
44
|
+
"%0#{octal_length}o" % value
|
27
45
|
end
|
28
46
|
|
29
|
-
|
47
|
+
# :reek:TooManyStatements { max_statements: 8}
|
48
|
+
# :reek:UncommunicativeMethodName
|
49
|
+
private_class_method def self.to_base256(value, length)
|
30
50
|
encoded = Array.new(length, 0)
|
31
51
|
encoded[0] = 0x80
|
32
52
|
index = length - 1
|
@@ -40,12 +60,5 @@ module MiniTarball
|
|
40
60
|
|
41
61
|
encoded.pack("C#{length}")
|
42
62
|
end
|
43
|
-
|
44
|
-
# Removes file type bitfields and returns file permissions as formatted number
|
45
|
-
# @param value [Integer]
|
46
|
-
# @param length [Integer]
|
47
|
-
def self.format_permissions(value, length)
|
48
|
-
format_number(value & PERMISSION_BITMASK, length)
|
49
|
-
end
|
50
63
|
end
|
51
64
|
end
|
@@ -7,79 +7,17 @@ module MiniTarball
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def write(header)
|
10
|
-
write_long_name_header(header) if has_long_name?
|
11
|
-
@io.write(to_binary
|
10
|
+
write_long_name_header(header) if header.has_long_name?
|
11
|
+
@io.write(header.to_binary)
|
12
12
|
end
|
13
13
|
|
14
|
-
private
|
15
|
-
|
16
|
-
def to_binary(header)
|
17
|
-
values_by_field = {}
|
18
|
-
|
19
|
-
Header::FIELDS.each do |name, field|
|
20
|
-
value = values_by_field[name] = header.value_of(name)
|
21
|
-
|
22
|
-
case field[:type]
|
23
|
-
when :number
|
24
|
-
values_by_field[name] = HeaderFormatter.format_number(value, field[:length])
|
25
|
-
when :mode
|
26
|
-
values_by_field[name] = HeaderFormatter.format_permissions(value, field[:length])
|
27
|
-
when :checksum
|
28
|
-
values_by_field[name] = " " * field[:length]
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
update_checksum(values_by_field)
|
33
|
-
add_padding(encode(values_by_field.values))
|
34
|
-
end
|
35
|
-
|
36
|
-
def update_checksum(values_by_field)
|
37
|
-
checksum = encode(values_by_field.values).unpack("C*").sum
|
38
|
-
values_by_field[:checksum] = format_checksum(checksum)
|
39
|
-
end
|
40
|
-
|
41
|
-
def format_checksum(checksum)
|
42
|
-
length = Header::FIELDS[:checksum][:length] - 1
|
43
|
-
HeaderFormatter.format_number(checksum, length) << "\0 "
|
44
|
-
end
|
45
|
-
|
46
|
-
def encode(values)
|
47
|
-
@pack_format ||= Header::FIELDS.values
|
48
|
-
.map { |field| "a#{field[:length]}" }
|
49
|
-
.join("")
|
50
|
-
|
51
|
-
values.pack(@pack_format)
|
52
|
-
end
|
53
|
-
|
54
|
-
def add_padding(binary)
|
55
|
-
padding_length = (Header::BLOCK_SIZE - binary.length) % Header::BLOCK_SIZE
|
56
|
-
binary << "\0" * padding_length
|
57
|
-
end
|
58
|
-
|
59
|
-
def has_long_name?(header)
|
60
|
-
header.value_of(:name).bytesize > Header::FIELDS[:name][:length]
|
61
|
-
end
|
62
|
-
|
63
|
-
def write_long_name_header(header)
|
14
|
+
private def write_long_name_header(header)
|
64
15
|
name = header.value_of(:name)
|
65
|
-
private_header = long_link_header(name
|
66
|
-
|
67
|
-
|
68
|
-
@io.write(to_binary(private_header))
|
69
|
-
@io.write(add_padding(data))
|
70
|
-
end
|
16
|
+
private_header = Header.long_link_header(name)
|
17
|
+
binary_data = [name].pack("Z*")
|
71
18
|
|
72
|
-
|
73
|
-
|
74
|
-
name: "././@LongLink",
|
75
|
-
mode: 0644,
|
76
|
-
uid: 0,
|
77
|
-
gid: 0,
|
78
|
-
size: name.bytesize + 1,
|
79
|
-
typeflag: type,
|
80
|
-
uname: "root",
|
81
|
-
gname: "root"
|
82
|
-
)
|
19
|
+
@io.write(private_header.to_binary)
|
20
|
+
@io.write(HeaderFormatter.zero_pad(binary_data))
|
83
21
|
end
|
84
22
|
end
|
85
23
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module MiniTarball
|
4
|
-
class WriteOutOfRangeError < StandardError
|
4
|
+
class WriteOutOfRangeError < StandardError
|
5
|
+
end
|
5
6
|
|
6
7
|
class LimitedSizeStream
|
7
8
|
attr_reader :start_position, :end_position
|
9
|
+
attr_reader :io
|
10
|
+
private :io # TODO change to `private attr_reader :io` after dropping support for Ruby 2.7
|
8
11
|
|
9
12
|
def initialize(io, start_position:, max_file_size:)
|
10
13
|
@io = io
|
@@ -13,11 +16,13 @@ module MiniTarball
|
|
13
16
|
end
|
14
17
|
|
15
18
|
def write(data)
|
16
|
-
|
19
|
+
current_position = io.pos
|
20
|
+
|
21
|
+
if current_position < start_position || current_position + data.bytesize > end_position
|
17
22
|
raise WriteOutOfRangeError.new("Writing outside of limits not allowed")
|
18
23
|
end
|
19
24
|
|
20
|
-
|
25
|
+
io.write(data)
|
21
26
|
end
|
22
27
|
end
|
23
28
|
end
|
@@ -8,7 +8,10 @@ module MiniTarball
|
|
8
8
|
|
9
9
|
def write(data)
|
10
10
|
super(data)
|
11
|
-
|
11
|
+
|
12
|
+
if (current_position = io.pos) <= end_position
|
13
|
+
io.write("\0" * (end_position - current_position))
|
14
|
+
end
|
12
15
|
end
|
13
16
|
end
|
14
17
|
end
|
data/lib/mini_tarball/version.rb
CHANGED
data/lib/mini_tarball/writer.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "etc"
|
4
4
|
|
5
5
|
module MiniTarball
|
6
|
+
class NoIOLikeObjectError < StandardError
|
7
|
+
end
|
8
|
+
|
6
9
|
class Writer
|
7
10
|
END_OF_TAR_BLOCK_SIZE = 1024
|
8
11
|
|
9
12
|
# @param [String] filename
|
10
13
|
# @yieldparam [Writer]
|
14
|
+
#
|
15
|
+
# :reek:NestedIterators
|
11
16
|
def self.create(filename)
|
12
|
-
File.open(filename, "wb")
|
13
|
-
use(file) { |writer| yield(writer) }
|
14
|
-
end
|
17
|
+
File.open(filename, "wb") { |file| use(file) { |writer| yield(writer) } }
|
15
18
|
end
|
16
19
|
|
17
20
|
# @param [IO] io
|
@@ -29,7 +32,7 @@ module MiniTarball
|
|
29
32
|
end
|
30
33
|
|
31
34
|
def initialize(io)
|
32
|
-
ensure_valid_io
|
35
|
+
ensure_valid_io(io)
|
33
36
|
|
34
37
|
@io = io
|
35
38
|
@write_only_io = WriteOnlyStream.new(@io)
|
@@ -38,30 +41,59 @@ module MiniTarball
|
|
38
41
|
@placeholders = []
|
39
42
|
end
|
40
43
|
|
41
|
-
|
42
|
-
|
44
|
+
# :reek:ControlParameter
|
45
|
+
# :reek:DuplicateMethodCall { allow_calls: ['stat.uid', 'stat.gid'] }
|
46
|
+
# :reek:FeatureEnvy
|
47
|
+
# :reek:LongParameterList
|
48
|
+
# :reek:TooManyStatements
|
49
|
+
def add_file(
|
50
|
+
name:,
|
51
|
+
source_file_path:,
|
52
|
+
mode: nil,
|
53
|
+
uname: nil,
|
54
|
+
gname: nil,
|
55
|
+
uid: nil,
|
56
|
+
gid: nil,
|
57
|
+
mtime: nil
|
58
|
+
)
|
59
|
+
ensure_not_closed
|
43
60
|
|
44
|
-
file = File.open(source_file_path, "rb")
|
45
61
|
stat = File.stat(source_file_path)
|
46
62
|
|
47
|
-
@header_writer.write(
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
63
|
+
@header_writer.write(
|
64
|
+
Header.new(
|
65
|
+
name: name,
|
66
|
+
size: stat.size,
|
67
|
+
mode: mode || stat.mode,
|
68
|
+
uid: uid || stat.uid,
|
69
|
+
gid: gid || stat.gid,
|
70
|
+
uname: uname || Etc.getpwuid(stat.uid).name,
|
71
|
+
gname: gname || Etc.getgrgid(stat.gid).name,
|
72
|
+
mtime: mtime || stat.mtime,
|
73
|
+
),
|
74
|
+
)
|
75
|
+
|
76
|
+
File.open(source_file_path, "rb") { |file| IO.copy_stream(file, @write_only_io) }
|
77
|
+
|
59
78
|
write_padding
|
60
79
|
nil
|
61
80
|
end
|
62
81
|
|
63
|
-
|
64
|
-
|
82
|
+
# :reek:ControlParameter
|
83
|
+
# :reek:DuplicateMethodCall { allow_calls: ['@io.pos'] }
|
84
|
+
# :reek:LongParameterList
|
85
|
+
# :reek:TooManyStatements
|
86
|
+
def add_file_from_stream(
|
87
|
+
name:,
|
88
|
+
mode: 0644,
|
89
|
+
uname: "nobody",
|
90
|
+
gname: "nogroup",
|
91
|
+
uid: nil,
|
92
|
+
gid: nil,
|
93
|
+
mtime: nil
|
94
|
+
)
|
95
|
+
ensure_not_closed
|
96
|
+
ensure_seekable_io
|
65
97
|
|
66
98
|
header_start_position = @io.pos
|
67
99
|
@header_writer.write(Header.new(name: name))
|
@@ -72,23 +104,27 @@ module MiniTarball
|
|
72
104
|
write_padding
|
73
105
|
|
74
106
|
@io.seek(header_start_position)
|
75
|
-
@header_writer.write(
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
107
|
+
@header_writer.write(
|
108
|
+
Header.new(
|
109
|
+
name: name,
|
110
|
+
size: file_size,
|
111
|
+
mode: mode,
|
112
|
+
uid: uid,
|
113
|
+
gid: gid,
|
114
|
+
uname: uname,
|
115
|
+
gname: gname,
|
116
|
+
mtime: mtime || Time.now.utc,
|
117
|
+
),
|
118
|
+
)
|
85
119
|
|
86
120
|
@io.seek(0, IO::SEEK_END)
|
87
121
|
nil
|
88
122
|
end
|
89
123
|
|
124
|
+
# :reek:DuplicateMethodCall { allow_calls: ['@io.pos'] }
|
125
|
+
# :reek:TooManyStatements
|
90
126
|
def add_file_placeholder(name:, file_size:)
|
91
|
-
ensure_not_closed
|
127
|
+
ensure_not_closed
|
92
128
|
|
93
129
|
placeholder = {}
|
94
130
|
placeholder[:header_start_position] = @io.pos
|
@@ -104,17 +140,21 @@ module MiniTarball
|
|
104
140
|
@placeholders.size - 1
|
105
141
|
end
|
106
142
|
|
143
|
+
# :reek:TooManyStatements
|
107
144
|
def with_placeholder(index)
|
145
|
+
ensure_seekable_io
|
146
|
+
|
108
147
|
placeholder = @placeholders[index]
|
109
|
-
raise ArgumentError.new("Placeholder not found") if placeholder
|
148
|
+
raise ArgumentError.new("Placeholder not found") if !placeholder
|
110
149
|
|
111
150
|
@io.seek(placeholder[:header_start_position])
|
112
151
|
old_write_only_io = @write_only_io
|
113
|
-
@write_only_io =
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
152
|
+
@write_only_io =
|
153
|
+
PlaceholderStream.new(
|
154
|
+
@io,
|
155
|
+
start_position: placeholder[:file_start_position],
|
156
|
+
file_size: placeholder[:file_size],
|
157
|
+
)
|
118
158
|
|
119
159
|
yield self
|
120
160
|
|
@@ -129,25 +169,30 @@ module MiniTarball
|
|
129
169
|
end
|
130
170
|
|
131
171
|
def close
|
132
|
-
ensure_not_closed
|
172
|
+
ensure_not_closed
|
133
173
|
|
134
174
|
@io.write("\0" * END_OF_TAR_BLOCK_SIZE)
|
135
175
|
@io.close
|
136
176
|
@closed = true
|
137
177
|
end
|
138
178
|
|
139
|
-
|
179
|
+
# :reek:FeatureEnvy
|
180
|
+
# :reek:ManualDispatch
|
181
|
+
private def ensure_valid_io(io)
|
182
|
+
unless io.respond_to?(:pos) && io.respond_to?(:write) && io.respond_to?(:close)
|
183
|
+
raise NoIOLikeObjectError.new("No IO object given")
|
184
|
+
end
|
185
|
+
end
|
140
186
|
|
141
|
-
def
|
142
|
-
raise "No IO object given" unless io.respond_to?(:
|
143
|
-
io.respond_to?(:write) && io.respond_to?(:close)
|
187
|
+
private def ensure_seekable_io
|
188
|
+
raise NoIOLikeObjectError.new("No seekable IO object given") unless @io.respond_to?(:seek)
|
144
189
|
end
|
145
190
|
|
146
|
-
def ensure_not_closed
|
191
|
+
private def ensure_not_closed
|
147
192
|
raise IOError.new("#{self.class} is closed") if closed?
|
148
193
|
end
|
149
194
|
|
150
|
-
def write_padding
|
195
|
+
private def write_padding
|
151
196
|
padding_length = (Header::BLOCK_SIZE - @io.pos) % Header::BLOCK_SIZE
|
152
197
|
@io.write("\0" * padding_length)
|
153
198
|
end
|
data/lib/mini_tarball.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
3
|
+
require "mini_tarball/header"
|
4
|
+
require "mini_tarball/header_fields"
|
5
|
+
require "mini_tarball/header_formatter"
|
6
|
+
require "mini_tarball/header_writer"
|
7
|
+
require "mini_tarball/streams/limited_size_stream"
|
8
|
+
require "mini_tarball/streams/placeholder_stream"
|
9
|
+
require "mini_tarball/streams/write_only_stream"
|
10
|
+
require "mini_tarball/writer"
|
11
|
+
require "mini_tarball/version"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_tarball
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Discourse
|
7
|
+
- Discourse Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rubycritic
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: super_diff
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: syntax_tree
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
97
125
|
description:
|
98
126
|
email:
|
99
127
|
executables: []
|
@@ -103,6 +131,7 @@ files:
|
|
103
131
|
- LICENSE.txt
|
104
132
|
- lib/mini_tarball.rb
|
105
133
|
- lib/mini_tarball/header.rb
|
134
|
+
- lib/mini_tarball/header_fields.rb
|
106
135
|
- lib/mini_tarball/header_formatter.rb
|
107
136
|
- lib/mini_tarball/header_writer.rb
|
108
137
|
- lib/mini_tarball/streams/limited_size_stream.rb
|