and_feathers 0.0.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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +4 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +44 -0
- data/Rakefile +1 -0
- data/and_feathers.gemspec +23 -0
- data/lib/and_feathers.rb +36 -0
- data/lib/and_feathers/tarball.rb +75 -0
- data/lib/and_feathers/tarball/contains_directories.rb +24 -0
- data/lib/and_feathers/tarball/contains_files.rb +27 -0
- data/lib/and_feathers/tarball/directory.rb +66 -0
- data/lib/and_feathers/tarball/file.rb +60 -0
- data/lib/and_feathers/version.rb +3 -0
- data/spec/end_to_end_spec.rb +106 -0
- data/spec/support/in_memory_gzipped_tarball.rb +35 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1223a216ba02082494665468136a5511c39a9f1a
|
4
|
+
data.tar.gz: ab24c8bbac7301824b242bbb875c7ff88b3b60f4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ce15a3c45c91982cad44943259acd6575b49f28e639bfec316a307ab973434d61b50088604898f6ad0b618b42745c54cd7ac373185d2cf4b4c0bc27d774e883c
|
7
|
+
data.tar.gz: 3db4aa09d56d1d9829909d89bc5e246f2f38eeb112f4ed62643160319ac83375dda49a395ba3d7ee23563a2fffad723098837f6fb778d46a23396782c33d1f5a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Brian Cobb
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# AndFeathers
|
2
|
+
|
3
|
+
Declaratively build in-memory gzipped tarballs.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Either run:
|
8
|
+
|
9
|
+
$ gem install and_feathers
|
10
|
+
|
11
|
+
Or, if you're using Bundler, add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'and_feathers'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Suppose you want to create the equivalent of a Chef cookbook artifact created using knife:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'and_feathers'
|
25
|
+
require 'json'
|
26
|
+
|
27
|
+
tarball = AndFeathers.build('redis') do |redis|
|
28
|
+
redis.file('README.md') { "README content" }
|
29
|
+
redis.file('metadata.json') { JSON.dump({}) }
|
30
|
+
redis.file('metadata.rb') { "# metadata.rb content" }
|
31
|
+
redis.dir('attributes') do |attributes|
|
32
|
+
attributes.file('default.rb') { '# default.rb content' }
|
33
|
+
end
|
34
|
+
redis.dir('recipes') do |recipes|
|
35
|
+
attributes.file('default.rb') { '# default.rb content' }
|
36
|
+
end
|
37
|
+
redis.dir('templates') do |templates|
|
38
|
+
templates.dir('default')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
tarball.to_io # a gzipped, tarball StringIO
|
43
|
+
```
|
44
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'and_feathers/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "and_feathers"
|
8
|
+
spec.version = AndFeathers::VERSION
|
9
|
+
spec.authors = ["Brian Cobb"]
|
10
|
+
spec.email = ["bcobb@uwalumni.com"]
|
11
|
+
spec.summary = %q{Declaratively build GZipped Tarballs in memory}
|
12
|
+
spec.homepage = "http://github.com/bcobb/and_feathers"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
spec.add_development_dependency "rspec"
|
23
|
+
end
|
data/lib/and_feathers.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'and_feathers/tarball/file'
|
2
|
+
require 'and_feathers/tarball/directory'
|
3
|
+
require 'and_feathers/tarball'
|
4
|
+
require 'and_feathers/version'
|
5
|
+
|
6
|
+
#
|
7
|
+
# The entry-point to the builder DSL
|
8
|
+
#
|
9
|
+
module AndFeathers
|
10
|
+
#
|
11
|
+
# Builds a new +Tarball+. If +base+ is not given, the tarball's contents
|
12
|
+
# would be extracted to intermingle with whichever directory contains the
|
13
|
+
# tarball. If +base+ is given, the tarball's contents will live inside a
|
14
|
+
# directory with that name. This is just a convenient way to have a +dir+
|
15
|
+
# call wrap the tarball's contents
|
16
|
+
#
|
17
|
+
# @param base [String] name of the base directory containing the tarball's
|
18
|
+
# contents
|
19
|
+
# @param base_mode [Fixnum] the mode of the base directory
|
20
|
+
#
|
21
|
+
# @yieldparam tarball [Tarball]
|
22
|
+
#
|
23
|
+
def self.build(base = nil, base_mode = 16877, &block)
|
24
|
+
if base && base_mode
|
25
|
+
Tarball.new.tap do |tarball|
|
26
|
+
tarball.dir(base, base_mode) do |dir|
|
27
|
+
block.call(dir)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
else
|
31
|
+
Tarball.new.tap do |tarball|
|
32
|
+
block.call(tarball)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,75 @@
|
|
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
|
@@ -0,0 +1,24 @@
|
|
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
|
@@ -0,0 +1,27 @@
|
|
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
|
@@ -0,0 +1,66 @@
|
|
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
|
@@ -0,0 +1,60 @@
|
|
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
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'and_feathers'
|
2
|
+
require 'support/in_memory_gzipped_tarball'
|
3
|
+
|
4
|
+
describe AndFeathers do
|
5
|
+
|
6
|
+
describe 'a tarball with a base directory' do
|
7
|
+
let(:tarball) do
|
8
|
+
AndFeathers.build('redis') do |redis|
|
9
|
+
redis.dir('cookbooks') do |cookbooks|
|
10
|
+
cookbooks.dir('redis') do |redis|
|
11
|
+
redis.file('README') { 'README contents' }
|
12
|
+
redis.file('CHANGELOG') { 'CHANGELOG contents' }
|
13
|
+
redis.file('metadata.rb') { 'metadata.rb contents' }
|
14
|
+
redis.dir('recipes') do |recipes|
|
15
|
+
recipes.file('default.rb') { 'default.rb contents' }
|
16
|
+
end
|
17
|
+
redis.dir('templates') do |templates|
|
18
|
+
templates.dir('default')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:tree) do
|
26
|
+
[
|
27
|
+
'./redis',
|
28
|
+
'./redis/cookbooks',
|
29
|
+
'./redis/cookbooks/redis',
|
30
|
+
'./redis/cookbooks/redis/README',
|
31
|
+
'./redis/cookbooks/redis/CHANGELOG',
|
32
|
+
'./redis/cookbooks/redis/metadata.rb',
|
33
|
+
'./redis/cookbooks/redis/recipes',
|
34
|
+
'./redis/cookbooks/redis/recipes/default.rb',
|
35
|
+
'./redis/cookbooks/redis/templates',
|
36
|
+
'./redis/cookbooks/redis/templates/default'
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'iterates through each directory breadth-first' do
|
41
|
+
expect(tarball.to_a.map(&:path)).to eql(tree)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'can build an in-memory tarred/gzipped IO stream' do
|
45
|
+
reader = InMemoryGzippedTarball.new(tarball.to_io)
|
46
|
+
|
47
|
+
expect(reader.to_a.map(&:first)).to eql(tree)
|
48
|
+
expect(reader.to_a.map(&:last).reject(&:empty?)).to eq([
|
49
|
+
'README contents',
|
50
|
+
'CHANGELOG contents',
|
51
|
+
'metadata.rb contents',
|
52
|
+
'default.rb contents'
|
53
|
+
])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'a tarball without a base directory' do
|
58
|
+
let(:tarball) do
|
59
|
+
AndFeathers.build do |redis|
|
60
|
+
redis.dir('cookbooks') do |cookbooks|
|
61
|
+
cookbooks.dir('redis') do |redis|
|
62
|
+
redis.file('README') { 'README contents' }
|
63
|
+
redis.file('CHANGELOG') { 'CHANGELOG contents' }
|
64
|
+
redis.file('metadata.rb') { 'metadata.rb contents' }
|
65
|
+
redis.dir('recipes') do |recipes|
|
66
|
+
recipes.file('default.rb') { 'default.rb contents' }
|
67
|
+
end
|
68
|
+
redis.dir('templates') do |templates|
|
69
|
+
templates.dir('default')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
let(:tree) do
|
77
|
+
[
|
78
|
+
'./cookbooks',
|
79
|
+
'./cookbooks/redis',
|
80
|
+
'./cookbooks/redis/README',
|
81
|
+
'./cookbooks/redis/CHANGELOG',
|
82
|
+
'./cookbooks/redis/metadata.rb',
|
83
|
+
'./cookbooks/redis/recipes',
|
84
|
+
'./cookbooks/redis/recipes/default.rb',
|
85
|
+
'./cookbooks/redis/templates',
|
86
|
+
'./cookbooks/redis/templates/default'
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'iterates through each directory breadth-first' do
|
91
|
+
expect(tarball.to_a.map(&:path)).to eql(tree)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'can build an in-memory tarred/gzipped IO stream' do
|
95
|
+
reader = InMemoryGzippedTarball.new(tarball.to_io)
|
96
|
+
|
97
|
+
expect(reader.to_a.map(&:first)).to eql(tree)
|
98
|
+
expect(reader.to_a.map(&:last).reject(&:empty?)).to eq([
|
99
|
+
'README contents',
|
100
|
+
'CHANGELOG contents',
|
101
|
+
'metadata.rb contents',
|
102
|
+
'default.rb contents'
|
103
|
+
])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems/package'
|
2
|
+
require 'zlib'
|
3
|
+
|
4
|
+
class InMemoryGzippedTarball
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
NotUnzipped = Object.new
|
8
|
+
|
9
|
+
def initialize(file)
|
10
|
+
@file = file
|
11
|
+
@unzipped = NotUnzipped
|
12
|
+
end
|
13
|
+
|
14
|
+
def each
|
15
|
+
if NotUnzipped == @unzipped
|
16
|
+
reader = Zlib::GzipReader.new(@file)
|
17
|
+
@unzipped = StringIO.new(reader.read).tap do
|
18
|
+
reader.close
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Gem::Package::TarReader.new(@unzipped)do |tar|
|
23
|
+
tar.each do |tarfile|
|
24
|
+
if tarfile.directory?
|
25
|
+
yield tarfile.full_name, ''
|
26
|
+
else
|
27
|
+
yield tarfile.full_name, tarfile.read
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
ensure
|
32
|
+
@unzipped.rewind
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: and_feathers
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Cobb
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- bcobb@uwalumni.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- .rspec
|
64
|
+
- .ruby-version
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE.txt
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- and_feathers.gemspec
|
70
|
+
- lib/and_feathers.rb
|
71
|
+
- lib/and_feathers/tarball.rb
|
72
|
+
- lib/and_feathers/tarball/contains_directories.rb
|
73
|
+
- lib/and_feathers/tarball/contains_files.rb
|
74
|
+
- lib/and_feathers/tarball/directory.rb
|
75
|
+
- lib/and_feathers/tarball/file.rb
|
76
|
+
- lib/and_feathers/version.rb
|
77
|
+
- spec/end_to_end_spec.rb
|
78
|
+
- spec/support/in_memory_gzipped_tarball.rb
|
79
|
+
homepage: http://github.com/bcobb/and_feathers
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.0.3
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Declaratively build GZipped Tarballs in memory
|
103
|
+
test_files:
|
104
|
+
- spec/end_to_end_spec.rb
|
105
|
+
- spec/support/in_memory_gzipped_tarball.rb
|
106
|
+
has_rdoc:
|