gel 0.2.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 +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/exe/gel +13 -0
- data/lib/gel.rb +22 -0
- data/lib/gel/catalog.rb +153 -0
- data/lib/gel/catalog/common.rb +82 -0
- data/lib/gel/catalog/compact_index.rb +152 -0
- data/lib/gel/catalog/dependency_index.rb +125 -0
- data/lib/gel/catalog/legacy_index.rb +157 -0
- data/lib/gel/catalog/marshal_hacks.rb +16 -0
- data/lib/gel/command.rb +86 -0
- data/lib/gel/command/config.rb +11 -0
- data/lib/gel/command/env.rb +7 -0
- data/lib/gel/command/exec.rb +66 -0
- data/lib/gel/command/help.rb +7 -0
- data/lib/gel/command/install.rb +7 -0
- data/lib/gel/command/install_gem.rb +16 -0
- data/lib/gel/command/lock.rb +34 -0
- data/lib/gel/command/ruby.rb +10 -0
- data/lib/gel/command/shell_setup.rb +25 -0
- data/lib/gel/command/stub.rb +12 -0
- data/lib/gel/command/update.rb +11 -0
- data/lib/gel/compatibility.rb +4 -0
- data/lib/gel/compatibility/bundler.rb +54 -0
- data/lib/gel/compatibility/bundler/cli.rb +6 -0
- data/lib/gel/compatibility/bundler/friendly_errors.rb +3 -0
- data/lib/gel/compatibility/bundler/setup.rb +4 -0
- data/lib/gel/compatibility/rubygems.rb +192 -0
- data/lib/gel/compatibility/rubygems/command.rb +4 -0
- data/lib/gel/compatibility/rubygems/dependency_installer.rb +0 -0
- data/lib/gel/compatibility/rubygems/gem_runner.rb +6 -0
- data/lib/gel/config.rb +80 -0
- data/lib/gel/db.rb +294 -0
- data/lib/gel/direct_gem.rb +29 -0
- data/lib/gel/environment.rb +592 -0
- data/lib/gel/error.rb +104 -0
- data/lib/gel/gemfile_parser.rb +144 -0
- data/lib/gel/gemspec_parser.rb +95 -0
- data/lib/gel/git_catalog.rb +38 -0
- data/lib/gel/git_depot.rb +119 -0
- data/lib/gel/httpool.rb +148 -0
- data/lib/gel/installer.rb +251 -0
- data/lib/gel/lock_loader.rb +164 -0
- data/lib/gel/lock_parser.rb +64 -0
- data/lib/gel/locked_store.rb +126 -0
- data/lib/gel/multi_store.rb +96 -0
- data/lib/gel/package.rb +156 -0
- data/lib/gel/package/inspector.rb +23 -0
- data/lib/gel/package/installer.rb +267 -0
- data/lib/gel/path_catalog.rb +44 -0
- data/lib/gel/pinboard.rb +140 -0
- data/lib/gel/pub_grub/preference_strategy.rb +82 -0
- data/lib/gel/pub_grub/source.rb +153 -0
- data/lib/gel/runtime.rb +27 -0
- data/lib/gel/store.rb +205 -0
- data/lib/gel/store_catalog.rb +31 -0
- data/lib/gel/store_gem.rb +80 -0
- data/lib/gel/stub_set.rb +51 -0
- data/lib/gel/support/gem_platform.rb +225 -0
- data/lib/gel/support/gem_requirement.rb +264 -0
- data/lib/gel/support/gem_version.rb +398 -0
- data/lib/gel/support/tar.rb +13 -0
- data/lib/gel/support/tar/tar_header.rb +229 -0
- data/lib/gel/support/tar/tar_reader.rb +123 -0
- data/lib/gel/support/tar/tar_reader/entry.rb +154 -0
- data/lib/gel/support/tar/tar_writer.rb +339 -0
- data/lib/gel/tail_file.rb +205 -0
- data/lib/gel/version.rb +5 -0
- data/lib/gel/work_pool.rb +143 -0
- data/man/man1/gel-exec.1 +16 -0
- data/man/man1/gel-install.1 +16 -0
- data/man/man1/gel.1 +30 -0
- metadata +131 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
|
5
|
+
# Redistributed under the terms of the MIT license.
|
6
|
+
#++
|
7
|
+
|
8
|
+
##
|
9
|
+
# TarReader reads tar files and allows iteration over their items
|
10
|
+
|
11
|
+
class Gel::Support::Tar::TarReader
|
12
|
+
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
##
|
16
|
+
# Raised if the tar IO is not seekable
|
17
|
+
|
18
|
+
class UnexpectedEOF < StandardError; end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Creates a new TarReader on +io+ and yields it to the block, if given.
|
22
|
+
|
23
|
+
def self.new(io)
|
24
|
+
reader = super
|
25
|
+
|
26
|
+
return reader unless block_given?
|
27
|
+
|
28
|
+
begin
|
29
|
+
yield reader
|
30
|
+
ensure
|
31
|
+
reader.close
|
32
|
+
end
|
33
|
+
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Creates a new tar file reader on +io+ which needs to respond to #pos,
|
39
|
+
# #eof?, #read, #getc and #pos=
|
40
|
+
|
41
|
+
def initialize(io)
|
42
|
+
@io = io
|
43
|
+
@init_pos = io.pos
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Close the tar file
|
48
|
+
|
49
|
+
def close
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Iterates over files in the tarball yielding each entry
|
54
|
+
|
55
|
+
def each
|
56
|
+
return enum_for __method__ unless block_given?
|
57
|
+
|
58
|
+
until @io.eof? do
|
59
|
+
header = Gel::Support::Tar::TarHeader.from @io
|
60
|
+
return if header.empty?
|
61
|
+
|
62
|
+
entry = Gel::Support::Tar::TarReader::Entry.new header, @io
|
63
|
+
size = entry.header.size
|
64
|
+
|
65
|
+
yield entry
|
66
|
+
|
67
|
+
skip = (512 - (size % 512)) % 512
|
68
|
+
pending = size - entry.bytes_read
|
69
|
+
|
70
|
+
begin
|
71
|
+
# avoid reading...
|
72
|
+
@io.seek pending, IO::SEEK_CUR
|
73
|
+
pending = 0
|
74
|
+
rescue Errno::EINVAL, NameError
|
75
|
+
while pending > 0 do
|
76
|
+
bytes_read = @io.read([pending, 4096].min).size
|
77
|
+
raise UnexpectedEOF if @io.eof?
|
78
|
+
pending -= bytes_read
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
@io.read skip # discard trailing zeros
|
83
|
+
|
84
|
+
# make sure nobody can use #read, #getc or #rewind anymore
|
85
|
+
entry.close
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
alias each_entry each
|
90
|
+
|
91
|
+
##
|
92
|
+
# NOTE: Do not call #rewind during #each
|
93
|
+
|
94
|
+
def rewind
|
95
|
+
if @init_pos == 0 then
|
96
|
+
raise Gel::Support::Tar::NonSeekableIO unless @io.respond_to? :rewind
|
97
|
+
@io.rewind
|
98
|
+
else
|
99
|
+
raise Gel::Support::Tar::NonSeekableIO unless @io.respond_to? :pos=
|
100
|
+
@io.pos = @init_pos
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Seeks through the tar file until it finds the +entry+ with +name+ and
|
106
|
+
# yields it. Rewinds the tar file to the beginning when the block
|
107
|
+
# terminates.
|
108
|
+
|
109
|
+
def seek name # :yields: entry
|
110
|
+
found = find do |entry|
|
111
|
+
entry.full_name == name
|
112
|
+
end
|
113
|
+
|
114
|
+
return unless found
|
115
|
+
|
116
|
+
return yield found
|
117
|
+
ensure
|
118
|
+
rewind
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
require_relative "tar_reader/entry"
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#++
|
4
|
+
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
|
5
|
+
# Redistributed under the terms of the MIT license.
|
6
|
+
#--
|
7
|
+
|
8
|
+
##
|
9
|
+
# Class for reading entries out of a tar file
|
10
|
+
|
11
|
+
class Gel::Support::Tar::TarReader::Entry
|
12
|
+
|
13
|
+
##
|
14
|
+
# Header for this tar entry
|
15
|
+
|
16
|
+
attr_reader :header
|
17
|
+
|
18
|
+
##
|
19
|
+
# Creates a new tar entry for +header+ that will be read from +io+
|
20
|
+
|
21
|
+
def initialize(header, io)
|
22
|
+
@closed = false
|
23
|
+
@header = header
|
24
|
+
@io = io
|
25
|
+
@orig_pos = @io.pos
|
26
|
+
@read = 0
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_closed # :nodoc:
|
30
|
+
raise IOError, "closed #{self.class}" if closed?
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Number of bytes read out of the tar entry
|
35
|
+
|
36
|
+
def bytes_read
|
37
|
+
@read
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Closes the tar entry
|
42
|
+
|
43
|
+
def close
|
44
|
+
@closed = true
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Is the tar entry closed?
|
49
|
+
|
50
|
+
def closed?
|
51
|
+
@closed
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Are we at the end of the tar entry?
|
56
|
+
|
57
|
+
def eof?
|
58
|
+
check_closed
|
59
|
+
|
60
|
+
@read >= @header.size
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Full name of the tar entry
|
65
|
+
|
66
|
+
def full_name
|
67
|
+
if @header.prefix != "" then
|
68
|
+
File.join @header.prefix, @header.name
|
69
|
+
else
|
70
|
+
@header.name
|
71
|
+
end
|
72
|
+
rescue ArgumentError => e
|
73
|
+
raise unless e.message == 'string contains null byte'
|
74
|
+
raise Gel::Support::Tar::TarInvalidError,
|
75
|
+
'tar is corrupt, name contains null byte'
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Read one byte from the tar entry
|
80
|
+
|
81
|
+
def getc
|
82
|
+
check_closed
|
83
|
+
|
84
|
+
return nil if @read >= @header.size
|
85
|
+
|
86
|
+
ret = @io.getc
|
87
|
+
@read += 1 if ret
|
88
|
+
|
89
|
+
ret
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Is this tar entry a directory?
|
94
|
+
|
95
|
+
def directory?
|
96
|
+
@header.typeflag == "5"
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Is this tar entry a file?
|
101
|
+
|
102
|
+
def file?
|
103
|
+
@header.typeflag == "0"
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# Is this tar entry a symlink?
|
108
|
+
|
109
|
+
def symlink?
|
110
|
+
@header.typeflag == "2"
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# The position in the tar entry
|
115
|
+
|
116
|
+
def pos
|
117
|
+
check_closed
|
118
|
+
|
119
|
+
bytes_read
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Reads +len+ bytes from the tar file entry, or the rest of the entry if
|
124
|
+
# nil
|
125
|
+
|
126
|
+
def read(len = nil)
|
127
|
+
check_closed
|
128
|
+
|
129
|
+
return nil if @read >= @header.size
|
130
|
+
|
131
|
+
len ||= @header.size - @read
|
132
|
+
max_read = [len, @header.size - @read].min
|
133
|
+
|
134
|
+
ret = @io.read max_read
|
135
|
+
@read += ret.size
|
136
|
+
|
137
|
+
ret
|
138
|
+
end
|
139
|
+
|
140
|
+
alias readpartial read # :nodoc:
|
141
|
+
|
142
|
+
##
|
143
|
+
# Rewinds to the beginning of the tar file entry
|
144
|
+
|
145
|
+
def rewind
|
146
|
+
check_closed
|
147
|
+
|
148
|
+
raise Gel::Support::Tar::NonSeekableIO unless @io.respond_to? :pos=
|
149
|
+
|
150
|
+
@io.pos = @orig_pos
|
151
|
+
@read = 0
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
@@ -0,0 +1,339 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
|
5
|
+
# Redistributed under the terms of the MIT license.
|
6
|
+
#++
|
7
|
+
|
8
|
+
require 'digest'
|
9
|
+
|
10
|
+
##
|
11
|
+
# Allows writing of tar files
|
12
|
+
|
13
|
+
class Gel::Support::Tar::TarWriter
|
14
|
+
|
15
|
+
class FileOverflow < StandardError; end
|
16
|
+
|
17
|
+
##
|
18
|
+
# IO wrapper that allows writing a limited amount of data
|
19
|
+
|
20
|
+
class BoundedStream
|
21
|
+
|
22
|
+
##
|
23
|
+
# Maximum number of bytes that can be written
|
24
|
+
|
25
|
+
attr_reader :limit
|
26
|
+
|
27
|
+
##
|
28
|
+
# Number of bytes written
|
29
|
+
|
30
|
+
attr_reader :written
|
31
|
+
|
32
|
+
##
|
33
|
+
# Wraps +io+ and allows up to +limit+ bytes to be written
|
34
|
+
|
35
|
+
def initialize(io, limit)
|
36
|
+
@io = io
|
37
|
+
@limit = limit
|
38
|
+
@written = 0
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Writes +data+ onto the IO, raising a FileOverflow exception if the
|
43
|
+
# number of bytes will be more than #limit
|
44
|
+
|
45
|
+
def write(data)
|
46
|
+
if data.bytesize + @written > @limit
|
47
|
+
raise FileOverflow, "You tried to feed more data than fits in the file."
|
48
|
+
end
|
49
|
+
@io.write data
|
50
|
+
@written += data.bytesize
|
51
|
+
data.bytesize
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# IO wrapper that provides only #write
|
58
|
+
|
59
|
+
class RestrictedStream
|
60
|
+
|
61
|
+
##
|
62
|
+
# Creates a new RestrictedStream wrapping +io+
|
63
|
+
|
64
|
+
def initialize(io)
|
65
|
+
@io = io
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Writes +data+ onto the IO
|
70
|
+
|
71
|
+
def write(data)
|
72
|
+
@io.write data
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Creates a new TarWriter, yielding it if a block is given
|
79
|
+
|
80
|
+
def self.new(io)
|
81
|
+
writer = super
|
82
|
+
|
83
|
+
return writer unless block_given?
|
84
|
+
|
85
|
+
begin
|
86
|
+
yield writer
|
87
|
+
ensure
|
88
|
+
writer.close
|
89
|
+
end
|
90
|
+
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Creates a new TarWriter that will write to +io+
|
96
|
+
|
97
|
+
def initialize(io)
|
98
|
+
@io = io
|
99
|
+
@closed = false
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Adds file +name+ with permissions +mode+, and yields an IO for writing the
|
104
|
+
# file to
|
105
|
+
|
106
|
+
def add_file(name, mode) # :yields: io
|
107
|
+
check_closed
|
108
|
+
|
109
|
+
raise Gel::Support::Tar::NonSeekableIO unless @io.respond_to? :pos=
|
110
|
+
|
111
|
+
name, prefix = split_name name
|
112
|
+
|
113
|
+
init_pos = @io.pos
|
114
|
+
@io.write "\0" * 512 # placeholder for the header
|
115
|
+
|
116
|
+
yield RestrictedStream.new(@io) if block_given?
|
117
|
+
|
118
|
+
size = @io.pos - init_pos - 512
|
119
|
+
|
120
|
+
remainder = (512 - (size % 512)) % 512
|
121
|
+
@io.write "\0" * remainder
|
122
|
+
|
123
|
+
final_pos = @io.pos
|
124
|
+
@io.pos = init_pos
|
125
|
+
|
126
|
+
header = Gel::Support::Tar::TarHeader.new :name => name, :mode => mode,
|
127
|
+
:size => size, :prefix => prefix,
|
128
|
+
:mtime => Time.now
|
129
|
+
|
130
|
+
@io.write header
|
131
|
+
@io.pos = final_pos
|
132
|
+
|
133
|
+
self
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Adds +name+ with permissions +mode+ to the tar, yielding +io+ for writing
|
138
|
+
# the file. The +digest_algorithm+ is written to a read-only +name+.sum
|
139
|
+
# file following the given file contents containing the digest name and
|
140
|
+
# hexdigest separated by a tab.
|
141
|
+
#
|
142
|
+
# The created digest object is returned.
|
143
|
+
|
144
|
+
def add_file_digest name, mode, digest_algorithms # :yields: io
|
145
|
+
digests = digest_algorithms.map do |digest_algorithm|
|
146
|
+
digest = digest_algorithm.new
|
147
|
+
digest_name =
|
148
|
+
if digest.respond_to? :name then
|
149
|
+
digest.name
|
150
|
+
else
|
151
|
+
/::([^:]+)$/ =~ digest_algorithm.name
|
152
|
+
$1
|
153
|
+
end
|
154
|
+
|
155
|
+
[digest_name, digest]
|
156
|
+
end
|
157
|
+
|
158
|
+
digests = Hash[*digests.flatten]
|
159
|
+
|
160
|
+
add_file name, mode do |io|
|
161
|
+
Gel::Support::Tar::DigestIO.wrap io, digests do |digest_io|
|
162
|
+
yield digest_io
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
digests
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Adds +name+ with permissions +mode+ to the tar, yielding +io+ for writing
|
171
|
+
# the file. The +signer+ is used to add a digest file using its
|
172
|
+
# digest_algorithm per add_file_digest and a cryptographic signature in
|
173
|
+
# +name+.sig. If the signer has no key only the checksum file is added.
|
174
|
+
#
|
175
|
+
# Returns the digest.
|
176
|
+
|
177
|
+
def add_file_signed name, mode, signer
|
178
|
+
digest_algorithms = [
|
179
|
+
signer.digest_algorithm,
|
180
|
+
Digest::SHA512,
|
181
|
+
].compact.uniq
|
182
|
+
|
183
|
+
digests = add_file_digest name, mode, digest_algorithms do |io|
|
184
|
+
yield io
|
185
|
+
end
|
186
|
+
|
187
|
+
signature_digest = digests.values.compact.find do |digest|
|
188
|
+
digest_name =
|
189
|
+
if digest.respond_to? :name then
|
190
|
+
digest.name
|
191
|
+
else
|
192
|
+
/::([^:]+)$/ =~ digest.class.name
|
193
|
+
$1
|
194
|
+
end
|
195
|
+
|
196
|
+
digest_name == signer.digest_name
|
197
|
+
end
|
198
|
+
|
199
|
+
if signer.key then
|
200
|
+
signature = signer.sign signature_digest.digest
|
201
|
+
|
202
|
+
add_file_simple "#{name}.sig", 0444, signature.length do |io|
|
203
|
+
io.write signature
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
digests
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# Add file +name+ with permissions +mode+ +size+ bytes long. Yields an IO
|
212
|
+
# to write the file to.
|
213
|
+
|
214
|
+
def add_file_simple(name, mode, size) # :yields: io
|
215
|
+
check_closed
|
216
|
+
|
217
|
+
name, prefix = split_name name
|
218
|
+
|
219
|
+
header = Gel::Support::Tar::TarHeader.new(:name => name, :mode => mode,
|
220
|
+
:size => size, :prefix => prefix,
|
221
|
+
:mtime => Time.now).to_s
|
222
|
+
|
223
|
+
@io.write header
|
224
|
+
os = BoundedStream.new @io, size
|
225
|
+
|
226
|
+
yield os if block_given?
|
227
|
+
|
228
|
+
min_padding = size - os.written
|
229
|
+
@io.write("\0" * min_padding)
|
230
|
+
|
231
|
+
remainder = (512 - (size % 512)) % 512
|
232
|
+
@io.write("\0" * remainder)
|
233
|
+
|
234
|
+
self
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# Adds symlink +name+ with permissions +mode+, linking to +target+.
|
239
|
+
|
240
|
+
def add_symlink(name, target, mode)
|
241
|
+
check_closed
|
242
|
+
|
243
|
+
name, prefix = split_name name
|
244
|
+
|
245
|
+
header = Gel::Support::Tar::TarHeader.new(:name => name, :mode => mode,
|
246
|
+
:size => 0, :typeflag => "2",
|
247
|
+
:linkname => target,
|
248
|
+
:prefix => prefix,
|
249
|
+
:mtime => Time.now).to_s
|
250
|
+
|
251
|
+
@io.write header
|
252
|
+
|
253
|
+
self
|
254
|
+
end
|
255
|
+
|
256
|
+
##
|
257
|
+
# Raises IOError if the TarWriter is closed
|
258
|
+
|
259
|
+
def check_closed
|
260
|
+
raise IOError, "closed #{self.class}" if closed?
|
261
|
+
end
|
262
|
+
|
263
|
+
##
|
264
|
+
# Closes the TarWriter
|
265
|
+
|
266
|
+
def close
|
267
|
+
check_closed
|
268
|
+
|
269
|
+
@io.write "\0" * 1024
|
270
|
+
flush
|
271
|
+
|
272
|
+
@closed = true
|
273
|
+
end
|
274
|
+
|
275
|
+
##
|
276
|
+
# Is the TarWriter closed?
|
277
|
+
|
278
|
+
def closed?
|
279
|
+
@closed
|
280
|
+
end
|
281
|
+
|
282
|
+
##
|
283
|
+
# Flushes the TarWriter's IO
|
284
|
+
|
285
|
+
def flush
|
286
|
+
check_closed
|
287
|
+
|
288
|
+
@io.flush if @io.respond_to? :flush
|
289
|
+
end
|
290
|
+
|
291
|
+
##
|
292
|
+
# Creates a new directory in the tar file +name+ with +mode+
|
293
|
+
|
294
|
+
def mkdir(name, mode)
|
295
|
+
check_closed
|
296
|
+
|
297
|
+
name, prefix = split_name(name)
|
298
|
+
|
299
|
+
header = Gel::Support::Tar::TarHeader.new :name => name, :mode => mode,
|
300
|
+
:typeflag => "5", :size => 0,
|
301
|
+
:prefix => prefix,
|
302
|
+
:mtime => Time.now
|
303
|
+
|
304
|
+
@io.write header
|
305
|
+
|
306
|
+
self
|
307
|
+
end
|
308
|
+
|
309
|
+
##
|
310
|
+
# Splits +name+ into a name and prefix that can fit in the TarHeader
|
311
|
+
|
312
|
+
def split_name(name) # :nodoc:
|
313
|
+
if name.bytesize > 256 then
|
314
|
+
raise Gel::Support::Tar::TooLongFileName.new("File \"#{name}\" has a too long path (should be 256 or less)")
|
315
|
+
end
|
316
|
+
|
317
|
+
prefix = ''
|
318
|
+
if name.bytesize > 100 then
|
319
|
+
parts = name.split('/', -1) # parts are never empty here
|
320
|
+
name = parts.pop # initially empty for names with a trailing slash ("foo/.../bar/")
|
321
|
+
prefix = parts.join('/') # if empty, then it's impossible to split (parts is empty too)
|
322
|
+
while !parts.empty? && (prefix.bytesize > 155 || name.empty?)
|
323
|
+
name = parts.pop + '/' + name
|
324
|
+
prefix = parts.join('/')
|
325
|
+
end
|
326
|
+
|
327
|
+
if name.bytesize > 100 or prefix.empty? then
|
328
|
+
raise Gel::Support::Tar::TooLongFileName.new("File \"#{prefix}/#{name}\" has a too long name (should be 100 or less)")
|
329
|
+
end
|
330
|
+
|
331
|
+
if prefix.bytesize > 155 then
|
332
|
+
raise Gel::Support::Tar::TooLongFileName.new("File \"#{prefix}/#{name}\" has a too long base path (should be 155 or less)")
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
return name, prefix
|
337
|
+
end
|
338
|
+
|
339
|
+
end
|