and_feathers 0.0.1 → 1.0.0.pre
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/.gitignore +1 -0
- data/.rspec +1 -1
- data/Gemfile +2 -0
- data/README.md +56 -10
- data/and_feathers.gemspec +2 -1
- data/lib/and_feathers/archive.rb +99 -0
- data/lib/and_feathers/directory.rb +155 -0
- data/lib/and_feathers/file.rb +66 -0
- data/lib/and_feathers/sugar.rb +105 -0
- data/lib/and_feathers/version.rb +6 -1
- data/lib/and_feathers.rb +58 -19
- data/spec/end_to_end/and_feathers_spec.rb +162 -0
- data/spec/fixtures/archiveme/README.md +1 -0
- data/spec/fixtures/archiveme/lib/archiveme.rb +2 -0
- data/spec/unit/directory_spec.rb +103 -0
- metadata +19 -15
- data/lib/and_feathers/tarball/contains_directories.rb +0 -24
- data/lib/and_feathers/tarball/contains_files.rb +0 -27
- data/lib/and_feathers/tarball/directory.rb +0 -66
- data/lib/and_feathers/tarball/file.rb +0 -60
- data/lib/and_feathers/tarball.rb +0 -75
- data/spec/end_to_end_spec.rb +0 -106
- data/spec/support/in_memory_gzipped_tarball.rb +0 -35
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'and_feathers'
|
2
|
+
|
3
|
+
describe AndFeathers do
|
4
|
+
|
5
|
+
describe 'building an archive with a base directory' do
|
6
|
+
let(:archive) do
|
7
|
+
AndFeathers.build('redis') do |redis|
|
8
|
+
redis.dir('cookbooks') do |cookbooks|
|
9
|
+
cookbooks.dir('redis') do |redis|
|
10
|
+
redis.file('README') { 'README contents' }
|
11
|
+
redis.file('CHANGELOG') { 'CHANGELOG contents' }
|
12
|
+
redis.file('metadata.rb') { 'metadata.rb contents' }
|
13
|
+
redis.dir('recipes') do |recipes|
|
14
|
+
recipes.file('default.rb') { 'default.rb contents' }
|
15
|
+
end
|
16
|
+
redis.dir('templates') do |templates|
|
17
|
+
templates.dir('default')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:tree) do
|
25
|
+
[
|
26
|
+
'./redis/cookbooks',
|
27
|
+
'./redis/cookbooks/redis',
|
28
|
+
'./redis/cookbooks/redis/README',
|
29
|
+
'./redis/cookbooks/redis/CHANGELOG',
|
30
|
+
'./redis/cookbooks/redis/metadata.rb',
|
31
|
+
'./redis/cookbooks/redis/recipes',
|
32
|
+
'./redis/cookbooks/redis/recipes/default.rb',
|
33
|
+
'./redis/cookbooks/redis/templates',
|
34
|
+
'./redis/cookbooks/redis/templates/default'
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'iterates through each directory depth-first' do
|
39
|
+
expect(archive.to_a.map(&:path)).to eql(tree)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'loads file content' do
|
43
|
+
files = archive.to_a.select { |e| e.is_a?(AndFeathers::File) }
|
44
|
+
expect(files.map(&:read)).to eql(
|
45
|
+
[
|
46
|
+
'README contents',
|
47
|
+
'CHANGELOG contents',
|
48
|
+
'metadata.rb contents',
|
49
|
+
'default.rb contents'
|
50
|
+
]
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'building an archive without a base directory' do
|
56
|
+
let(:archive) do
|
57
|
+
AndFeathers.build do |redis|
|
58
|
+
redis.dir('cookbooks') do |cookbooks|
|
59
|
+
cookbooks.dir('redis') do |redis|
|
60
|
+
redis.file('README') { 'README contents' }
|
61
|
+
redis.file('CHANGELOG') { 'CHANGELOG contents' }
|
62
|
+
redis.file('metadata.rb') { 'metadata.rb contents' }
|
63
|
+
redis.dir('recipes') do |recipes|
|
64
|
+
recipes.file('default.rb') { 'default.rb contents' }
|
65
|
+
end
|
66
|
+
redis.dir('templates') do |templates|
|
67
|
+
templates.dir('default')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
let(:tree) do
|
75
|
+
[
|
76
|
+
'./cookbooks',
|
77
|
+
'./cookbooks/redis',
|
78
|
+
'./cookbooks/redis/README',
|
79
|
+
'./cookbooks/redis/CHANGELOG',
|
80
|
+
'./cookbooks/redis/metadata.rb',
|
81
|
+
'./cookbooks/redis/recipes',
|
82
|
+
'./cookbooks/redis/recipes/default.rb',
|
83
|
+
'./cookbooks/redis/templates',
|
84
|
+
'./cookbooks/redis/templates/default'
|
85
|
+
]
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'iterates through each directory depth-first' do
|
89
|
+
expect(archive.to_a.map(&:path)).to eql(tree)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'loads file content' do
|
93
|
+
files = archive.to_a.select { |e| e.is_a?(AndFeathers::File) }
|
94
|
+
expect(files.map(&:read)).to eql(
|
95
|
+
[
|
96
|
+
'README contents',
|
97
|
+
'CHANGELOG contents',
|
98
|
+
'metadata.rb contents',
|
99
|
+
'default.rb contents'
|
100
|
+
]
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'loading an archive from an existing tree' do
|
106
|
+
let(:tree) do
|
107
|
+
[
|
108
|
+
'./archiveme/README.md',
|
109
|
+
'./archiveme/lib',
|
110
|
+
'./archiveme/lib/archiveme.rb'
|
111
|
+
]
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'iterates through a directory depth-first' do
|
115
|
+
archive = AndFeathers.from_path('spec/fixtures/archiveme')
|
116
|
+
|
117
|
+
expect(archive.to_a.map(&:path)).to eql(tree)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'loads file content' do
|
121
|
+
archive = AndFeathers.from_path('spec/fixtures/archiveme')
|
122
|
+
|
123
|
+
files = archive.to_a.select { |e| e.is_a?(AndFeathers::File) }
|
124
|
+
|
125
|
+
expect(files.map(&:read)).to eql(
|
126
|
+
["# Hello\n", "class Archiveme\nend\n"]
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'iterates through "." in the same way' do
|
131
|
+
archive = []
|
132
|
+
|
133
|
+
Dir.chdir('spec/fixtures/archiveme') do
|
134
|
+
archive = AndFeathers.from_path('.')
|
135
|
+
end
|
136
|
+
|
137
|
+
expect(archive.to_a.map(&:path)).to eql(tree)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'raises when the given path does not exist' do
|
141
|
+
expect do
|
142
|
+
AndFeathers.from_path('app')
|
143
|
+
end.to raise_error(ArgumentError)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'yields the resulting archive for modification', focus: true do
|
147
|
+
archive = AndFeathers.from_path('spec/fixtures/archiveme')
|
148
|
+
archive.file('lib/archiveme/version.rb') do
|
149
|
+
"class Archiveme\n VERSION='0.0.1'\nend"
|
150
|
+
end
|
151
|
+
archive.dir('tmp')
|
152
|
+
|
153
|
+
new_tree = [
|
154
|
+
'./archiveme/lib/archiveme',
|
155
|
+
'./archiveme/lib/archiveme/version.rb',
|
156
|
+
'./archiveme/tmp'
|
157
|
+
]
|
158
|
+
|
159
|
+
expect(archive.to_a.map(&:path)).to eql(tree + new_tree)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# Hello
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'and_feathers/file'
|
2
|
+
require 'and_feathers/directory'
|
3
|
+
|
4
|
+
module AndFeathers
|
5
|
+
describe Directory do
|
6
|
+
it 'can be unioned with another directory' do
|
7
|
+
one = Directory.new
|
8
|
+
two = Directory.new
|
9
|
+
one.dir('a') do |a|
|
10
|
+
a.dir('b') do |b|
|
11
|
+
b.file('c')
|
12
|
+
end
|
13
|
+
a.dir('c')
|
14
|
+
end
|
15
|
+
|
16
|
+
two.dir('a') do |a|
|
17
|
+
a.dir('b') do |b|
|
18
|
+
b.file('d')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
three = one | two
|
23
|
+
|
24
|
+
expect(three.to_a.map(&:path)).
|
25
|
+
to eql(['./a', './a/b', './a/b/c', './a/b/d', './a/c'])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'allows for manually nesting directories' do
|
29
|
+
archive = Directory.new
|
30
|
+
archive.dir('a') do |a|
|
31
|
+
a.dir('b') do |b|
|
32
|
+
b.dir('c')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
expect(archive.to_a.map(&:path)).to eql(['./a', './a/b', './a/b/c'])
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'allows for convenient nesting of directories' do
|
40
|
+
archive = Directory.new
|
41
|
+
archive.dir('a/b/c')
|
42
|
+
|
43
|
+
expect(archive.to_a.map(&:path)).to eql(['./a', './a/b', './a/b/c'])
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'only creates a given path once' do
|
47
|
+
archive = Directory.new
|
48
|
+
archive.dir('a/b/c')
|
49
|
+
archive.dir('a/b/c/d')
|
50
|
+
|
51
|
+
expect(archive.to_a.map(&:path)).
|
52
|
+
to eql(['./a', './a/b', './a/b/c', './a/b/c/d'])
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'takes the most recent duplicate directory as authoritative' do
|
56
|
+
archive = Directory.new
|
57
|
+
archive.dir('a/b/c')
|
58
|
+
archive.dir('a/b/d')
|
59
|
+
|
60
|
+
expect(archive.to_a.map(&:path)).to eql(['./a', './a/b', './a/b/d'])
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'allows for manually nesting files in directories' do
|
64
|
+
archive = Directory.new
|
65
|
+
archive.dir('a') do |a|
|
66
|
+
a.dir('b') do |b|
|
67
|
+
b.dir('c') do |c|
|
68
|
+
c.file 'README'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
expect(archive.to_a.map(&:path)).
|
74
|
+
to eql(['./a', './a/b', './a/b/c', './a/b/c/README'])
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'allows for convenient nesting of files in directories' do
|
78
|
+
archive = Directory.new
|
79
|
+
archive.file('a/b/c/README')
|
80
|
+
|
81
|
+
expect(archive.to_a.map(&:path)).
|
82
|
+
to eql(['./a', './a/b', './a/b/c', './a/b/c/README'])
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'only creates a given file once' do
|
86
|
+
archive = Directory.new
|
87
|
+
archive.file('a/README')
|
88
|
+
archive.file('a/README')
|
89
|
+
|
90
|
+
expect(archive.to_a.map(&:path)).to eql(['./a', './a/README'])
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'takes the most recent file as the authoritative file' do
|
94
|
+
archive = Directory.new
|
95
|
+
archive.file('a/README') { '1' }
|
96
|
+
archive.file('a/README') { '2' }
|
97
|
+
|
98
|
+
readme = archive.to_a.find { |e| e.is_a?(File) }
|
99
|
+
|
100
|
+
expect(readme.read).to eql('2')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: and_feathers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 1.0.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Cobb
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,7 +52,8 @@ dependencies:
|
|
52
52
|
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
description:
|
55
|
+
description: Declaratively and iteratively build archive structures which easily serialize
|
56
|
+
to on-disk formats such as zip and tgz.
|
56
57
|
email:
|
57
58
|
- bcobb@uwalumni.com
|
58
59
|
executables: []
|
@@ -68,14 +69,15 @@ files:
|
|
68
69
|
- Rakefile
|
69
70
|
- and_feathers.gemspec
|
70
71
|
- lib/and_feathers.rb
|
71
|
-
- lib/and_feathers/
|
72
|
-
- lib/and_feathers/
|
73
|
-
- lib/and_feathers/
|
74
|
-
- lib/and_feathers/
|
75
|
-
- lib/and_feathers/tarball/file.rb
|
72
|
+
- lib/and_feathers/archive.rb
|
73
|
+
- lib/and_feathers/directory.rb
|
74
|
+
- lib/and_feathers/file.rb
|
75
|
+
- lib/and_feathers/sugar.rb
|
76
76
|
- lib/and_feathers/version.rb
|
77
|
-
- spec/
|
78
|
-
- spec/
|
77
|
+
- spec/end_to_end/and_feathers_spec.rb
|
78
|
+
- spec/fixtures/archiveme/README.md
|
79
|
+
- spec/fixtures/archiveme/lib/archiveme.rb
|
80
|
+
- spec/unit/directory_spec.rb
|
79
81
|
homepage: http://github.com/bcobb/and_feathers
|
80
82
|
licenses:
|
81
83
|
- MIT
|
@@ -91,16 +93,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
93
|
version: '0'
|
92
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
95
|
requirements:
|
94
|
-
- - '
|
96
|
+
- - '>'
|
95
97
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
98
|
+
version: 1.3.1
|
97
99
|
requirements: []
|
98
100
|
rubyforge_project:
|
99
101
|
rubygems_version: 2.0.3
|
100
102
|
signing_key:
|
101
103
|
specification_version: 4
|
102
|
-
summary:
|
104
|
+
summary: In-memory archive structures
|
103
105
|
test_files:
|
104
|
-
- spec/
|
105
|
-
- spec/
|
106
|
+
- spec/end_to_end/and_feathers_spec.rb
|
107
|
+
- spec/fixtures/archiveme/README.md
|
108
|
+
- spec/fixtures/archiveme/lib/archiveme.rb
|
109
|
+
- spec/unit/directory_spec.rb
|
106
110
|
has_rdoc:
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module AndFeathers
|
2
|
-
class Tarball
|
3
|
-
#
|
4
|
-
# A module which gives instances of a class the +dir+ DSL method
|
5
|
-
#
|
6
|
-
module ContainsDirectories
|
7
|
-
#
|
8
|
-
# Add a +Directory+ named +name+ to this entity's list of children
|
9
|
-
#
|
10
|
-
# @param name [String] the directory name
|
11
|
-
# @param mode [Fixnum] the directory mode
|
12
|
-
#
|
13
|
-
# @yieldparam directory [Directory] the newly-created +Directory+
|
14
|
-
#
|
15
|
-
def dir(name, mode = 16877, &block)
|
16
|
-
Directory.new(name, mode, self).tap do |subdir|
|
17
|
-
block.call(subdir) if block
|
18
|
-
|
19
|
-
@children.push(subdir)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module AndFeathers
|
2
|
-
class Tarball
|
3
|
-
#
|
4
|
-
# A module which gives instances of a class the +file+ DSL method
|
5
|
-
#
|
6
|
-
module ContainsFiles
|
7
|
-
#
|
8
|
-
# The default file content block, which returns an empty string
|
9
|
-
#
|
10
|
-
NO_CONTENT = Proc.new { "" }
|
11
|
-
|
12
|
-
#
|
13
|
-
# Add a +File+ named +name+ to this entity's list of children
|
14
|
-
#
|
15
|
-
# @param name [String] the file name
|
16
|
-
# @param mode [Fixnum] the file mode
|
17
|
-
#
|
18
|
-
# @yieldreturn [String] the file contents
|
19
|
-
#
|
20
|
-
def file(name, mode = 33188, &content)
|
21
|
-
content ||= NO_CONTENT
|
22
|
-
|
23
|
-
@children.push(File.new(name, mode, content, self))
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'and_feathers/tarball/contains_files'
|
2
|
-
require 'and_feathers/tarball/contains_directories'
|
3
|
-
|
4
|
-
module AndFeathers
|
5
|
-
class Tarball
|
6
|
-
#
|
7
|
-
# Represents a Directory inside the tarball
|
8
|
-
#
|
9
|
-
class Directory
|
10
|
-
include Tarball::ContainsFiles
|
11
|
-
include Tarball::ContainsDirectories
|
12
|
-
|
13
|
-
attr_reader :name, :mode
|
14
|
-
|
15
|
-
#
|
16
|
-
# @!attribute [r] name
|
17
|
-
# @return [String] the directory name
|
18
|
-
#
|
19
|
-
# @!attribute [r] mode
|
20
|
-
# @return [Fixnum] the directory mode
|
21
|
-
#
|
22
|
-
|
23
|
-
#
|
24
|
-
# Creates a new +Directory+
|
25
|
-
#
|
26
|
-
# @param name [String] the directory name
|
27
|
-
# @param mode [Fixnum] the directory mode
|
28
|
-
# @param parent [Directory, Tarball] the parent entity of this directory
|
29
|
-
#
|
30
|
-
def initialize(name, mode, parent)
|
31
|
-
@name = name
|
32
|
-
@mode = mode
|
33
|
-
@parent = parent
|
34
|
-
@children = []
|
35
|
-
end
|
36
|
-
|
37
|
-
#
|
38
|
-
# This +Directory+'s path
|
39
|
-
#
|
40
|
-
# @return [String]
|
41
|
-
#
|
42
|
-
def path
|
43
|
-
::File.join(@parent.path, name)
|
44
|
-
end
|
45
|
-
|
46
|
-
#
|
47
|
-
# Iterates through this +Directory+'s children down to each leaf child.
|
48
|
-
#
|
49
|
-
# @yieldparam child [File, Directory]
|
50
|
-
#
|
51
|
-
def each(&block)
|
52
|
-
files, subdirectories = @children.partition do |child|
|
53
|
-
child.is_a?(File)
|
54
|
-
end
|
55
|
-
|
56
|
-
files.each(&block)
|
57
|
-
|
58
|
-
subdirectories.each do |subdirectory|
|
59
|
-
block.call(subdirectory)
|
60
|
-
|
61
|
-
subdirectory.each(&block)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
module AndFeathers
|
2
|
-
class Tarball
|
3
|
-
#
|
4
|
-
# Represents a File inside the tarball
|
5
|
-
#
|
6
|
-
class File
|
7
|
-
include Enumerable
|
8
|
-
|
9
|
-
attr_reader :name, :mode
|
10
|
-
|
11
|
-
#
|
12
|
-
# @!attribute [r] name
|
13
|
-
# @return [String] the directory name
|
14
|
-
#
|
15
|
-
# @!attribute [r] mode
|
16
|
-
# @return [Fixnum] the directory mode
|
17
|
-
#
|
18
|
-
|
19
|
-
#
|
20
|
-
# Creates a new +File+
|
21
|
-
#
|
22
|
-
# @param name [String] the file name
|
23
|
-
# @param mode [Fixnum] the file mode
|
24
|
-
# @param content [Proc] a block which returns the file contents
|
25
|
-
# @param parent [Directory, Tarball] the entity which contains this file
|
26
|
-
#
|
27
|
-
def initialize(name, mode, content, parent)
|
28
|
-
@name = name
|
29
|
-
@mode = mode
|
30
|
-
@content = content
|
31
|
-
@parent = parent
|
32
|
-
end
|
33
|
-
|
34
|
-
#
|
35
|
-
# This +File+'s path
|
36
|
-
#
|
37
|
-
# @return [String]
|
38
|
-
#
|
39
|
-
def path
|
40
|
-
::File.join(@parent.path, name)
|
41
|
-
end
|
42
|
-
|
43
|
-
#
|
44
|
-
# This +File+'s contents
|
45
|
-
#
|
46
|
-
def read
|
47
|
-
@content.call
|
48
|
-
end
|
49
|
-
|
50
|
-
#
|
51
|
-
# +Enumerable+ interface which simply yields this +File+ to the block
|
52
|
-
#
|
53
|
-
# @yieldparam file [File]
|
54
|
-
#
|
55
|
-
def each(&block)
|
56
|
-
block.call(self)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
data/lib/and_feathers/tarball.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'and_feathers/tarball/contains_files'
|
2
|
-
require 'and_feathers/tarball/contains_directories'
|
3
|
-
require 'rubygems/package'
|
4
|
-
require 'zlib'
|
5
|
-
|
6
|
-
module AndFeathers
|
7
|
-
#
|
8
|
-
# The base tarball representation
|
9
|
-
#
|
10
|
-
class Tarball
|
11
|
-
include ContainsFiles
|
12
|
-
include ContainsDirectories
|
13
|
-
include Enumerable
|
14
|
-
|
15
|
-
#
|
16
|
-
# @!attribute [r] path
|
17
|
-
# @return [String] the base tarball path
|
18
|
-
#
|
19
|
-
|
20
|
-
attr_reader :path
|
21
|
-
|
22
|
-
#
|
23
|
-
# Creates a new +Tarball+
|
24
|
-
#
|
25
|
-
# @param path [String] the base tarball path
|
26
|
-
#
|
27
|
-
def initialize(path = '.')
|
28
|
-
@path = path
|
29
|
-
@children = []
|
30
|
-
end
|
31
|
-
|
32
|
-
#
|
33
|
-
# Iterates through each entity in the tarball, depth-first
|
34
|
-
#
|
35
|
-
# @yieldparam child [File, Directory]
|
36
|
-
#
|
37
|
-
def each(&block)
|
38
|
-
@children.each do |child|
|
39
|
-
block.call(child)
|
40
|
-
child.each(&block)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
#
|
45
|
-
# Returns this +Tarball+ as a GZipped and tarred +StringIO+
|
46
|
-
#
|
47
|
-
# @return [StringIO]
|
48
|
-
#
|
49
|
-
def to_io
|
50
|
-
tarball_io = StringIO.new("")
|
51
|
-
|
52
|
-
Gem::Package::TarWriter.new(tarball_io) do |tar|
|
53
|
-
each do |child|
|
54
|
-
case child
|
55
|
-
when File
|
56
|
-
tar.add_file(child.path, child.mode) do |file|
|
57
|
-
file.write child.read
|
58
|
-
end
|
59
|
-
when Directory
|
60
|
-
tar.mkdir(child.path, child.mode)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
gzip_io = StringIO.new("")
|
66
|
-
|
67
|
-
Zlib::GzipWriter.new(gzip_io).tap do |writer|
|
68
|
-
writer.write(tarball_io.tap(&:rewind).string)
|
69
|
-
writer.close
|
70
|
-
end
|
71
|
-
|
72
|
-
StringIO.new(gzip_io.string)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|