verm-client 1.0.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/.gitignore +34 -0
- data/MIT-LICENSE +20 -0
- data/README.md +115 -0
- data/Rakefile +8 -0
- data/lib/verm.rb +1 -0
- data/lib/verm/client.rb +59 -0
- data/lib/verm/version.rb +3 -0
- data/test/fixtures/binary_file +0 -0
- data/test/fixtures/binary_file.gz +0 -0
- data/test/fixtures/large_compressed_csv_file.gz +0 -0
- data/test/verm_test.rb +109 -0
- data/verm.gemspec +21 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3a616e96483beae73fd10062005d641d30fb5352
|
4
|
+
data.tar.gz: 6b9fffb843d7d12a75c7cdb3658b193a740e5f32
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0aa23231f3b808815b44a89bf9cd81adf3e919affded5249c58ed6486aa41c4891f6d02427672c87b90e760047aed62b5033ec2dd8f1c9efe922c27d15997793
|
7
|
+
data.tar.gz: 9a333cbd52d2fc22b4e9389f0bb49f44592ffc26388bff151cb0795c9b54da62c89fd760f4556dbacb83ab57b0a3fedfdf974f1082bf75ffffe9bbd4ecf2ea4a
|
data/.gitignore
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
# Gemfile.lock
|
30
|
+
# .ruby-version
|
31
|
+
# .ruby-gemset
|
32
|
+
|
33
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
+
.rvmrc
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2015 Will Bryant, Sekuda Ltd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
20
|
+
|
data/README.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
Verm client library for Ruby
|
2
|
+
============================
|
3
|
+
|
4
|
+
Verm (https://github.com/willbryant/verm) is a WORM (write-once, read-many) file store to make it easy to reliably store and replicate files. Clients talk to Verm over simple HTTP POST and GET calls.
|
5
|
+
|
6
|
+
This tiny client library adds one-line convenience methods for storing files in Verm and retrieving/streaming them back again.
|
7
|
+
|
8
|
+
|
9
|
+
Saving content
|
10
|
+
--------------
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
mydata = "data to store"
|
14
|
+
VERM_CLIENT = Verm::Client.new("my-verm-server")
|
15
|
+
VERM_CLIENT.store("/important_gifs/january", mydata, "text/plain") # => String
|
16
|
+
```
|
17
|
+
|
18
|
+
The `store` call will return a path like `/important_gifs/january/ab/cdefgh.txt`, only longer (Verm makes the filename using an URL-safe base64 encoding of the SHA-256 of the content).
|
19
|
+
|
20
|
+
|
21
|
+
Saving files
|
22
|
+
------------
|
23
|
+
|
24
|
+
You don't need to read the whole file into memory before calling store, just pass the IO object in:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
VERM_CLIENT = Verm::Client.new("my-verm-server")
|
28
|
+
|
29
|
+
File.open("example.jpg", "rb") do |f|
|
30
|
+
VERM_CLIENT.store("/important_gifs/january", f, "image/jpeg") # => String
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
|
35
|
+
Retrieving content
|
36
|
+
------------------
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
VERM_CLIENT = Verm::Client.new("my-verm-server")
|
40
|
+
|
41
|
+
file, content_type = VERM_CLIENT.load("/important_gifs/january/ab/cdefgh.jpg")
|
42
|
+
```
|
43
|
+
|
44
|
+
This basically does the same thing as the built-in Net::HTTP get method (aside from timeouts, error handling, etc.):
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
Net::HTTP.get('my-verm-server:3404', '/important_gifs/january/ab/cdefgh.jpg') # => String - the file content
|
48
|
+
```
|
49
|
+
|
50
|
+
So you really don't need a client library for this - but it's usually more convenient to configure the Verm server somewhere central, instead of sprinkling it through your application.
|
51
|
+
|
52
|
+
Verm stores all content without touching its character encoding, but Ruby 1.9+ treats all strings as having a specific character encoding. Most applications use UTF-8 for all text, so by default, the `load` method will set the character encoding of `text/*` content returned by Verm to `UTF-8`. You can override this or disable it entirely:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
file, content_type = VERM_CLIENT.load("/important_gifs/january/ab/cdefgh.csv", force_encoding: 'ISO-8859-1')
|
56
|
+
file, content_type = VERM_CLIENT.load("/important_gifs/january/ab/cdefgh.csv", force_encoding: nil)
|
57
|
+
```
|
58
|
+
|
59
|
+
|
60
|
+
Retrieving large content
|
61
|
+
------------------------
|
62
|
+
|
63
|
+
If the data is large, reading it all into memory as a string is inefficient. Instead you can use `stream`, which will yield the file contents in chunks:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
VERM_CLIENT = Verm::Client.new("my-verm-server")
|
67
|
+
|
68
|
+
File.open("out.csv", "w") do |f|
|
69
|
+
VERM_CLIENT.stream("/big_data/ab/cdefgh.csv") do |chunk|
|
70
|
+
f.write chunk
|
71
|
+
end
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
Because the chunks may not be broken on a character encoding boundary, the character encoding can't be set as for `load`, so they will still have the default `ASCII-8BIT` binary encoding.
|
76
|
+
|
77
|
+
|
78
|
+
File compression
|
79
|
+
----------------
|
80
|
+
|
81
|
+
Like HTTP and web browsers, Verm treats gzip compression as being a way of making transfers smaller and faster, not a separate file type. So if you want to store gzipped files, you still get to say what content-type the actual file content has.
|
82
|
+
|
83
|
+
Saving files that are already gzip-compressed just requires one extra argument:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
File.open("acme_20150101.csv.gz", "rb") do |f|
|
87
|
+
VERM_CLIENT.store("/third_party_files/acme/2015", f, "text/csv", encoding: "gzip")
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
It's important to note that Ruby's Net::HTTP client will automatically uncompress gzip transfer-encoding on responses - so when you use `load` or `store`, you'll get the uncompressed content back, not the gzip file.
|
92
|
+
|
93
|
+
You can suppress that behavior by passing `Accept-Encoding: gzip` as a header (Net::HTTP would accept gzip anyway, but setting this header has the side effect of disabling uncompression):
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
file, content_type = VERM_CLIENT.load("/third_party_files/acme/2015/ab/cdefgh.csv", 'Accept-Encoding' => 'gzip')
|
97
|
+
```
|
98
|
+
|
99
|
+
|
100
|
+
Network stuff
|
101
|
+
-------------
|
102
|
+
|
103
|
+
Verm runs its HTTP server on port 3404 by default. You can override this in the client configuration:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
VERM_CLIENT = Verm::Client.new("my-verm-server", port: 80)
|
107
|
+
```
|
108
|
+
|
109
|
+
Verm::Client defaults to a 15s timeout, which you can override:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
VERM_CLIENT = Verm::Client.new("my-verm-server", timeout: 60)
|
113
|
+
```
|
114
|
+
|
115
|
+
Like Net::HTTP, this timeout applies to individual network operations, not the whole method.
|
data/Rakefile
ADDED
data/lib/verm.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'verm/client'
|
data/lib/verm/client.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Verm
|
4
|
+
class Client
|
5
|
+
attr_reader :http_client
|
6
|
+
|
7
|
+
def initialize(hostname, port: 3404, timeout: 15)
|
8
|
+
@http_client = Net::HTTP.new(hostname, port)
|
9
|
+
@http_client.open_timeout = timeout
|
10
|
+
@http_client.read_timeout = timeout
|
11
|
+
@http_client.ssl_timeout = timeout
|
12
|
+
end
|
13
|
+
|
14
|
+
def store(directory, io_or_data, content_type, encoding: nil)
|
15
|
+
directory = "/#{directory}" unless directory[0] == '/'
|
16
|
+
request = Net::HTTP::Post.new(directory, 'Content-Type' => content_type)
|
17
|
+
request['Content-Encoding'] = encoding.to_s if encoding
|
18
|
+
|
19
|
+
if io_or_data.respond_to?(:read)
|
20
|
+
request.body_stream = io_or_data
|
21
|
+
if io_or_data.respond_to?(:size)
|
22
|
+
request['Content-Length'] = io_or_data.size
|
23
|
+
else
|
24
|
+
request['Transfer-Encoding'] = 'chunked'
|
25
|
+
end
|
26
|
+
|
27
|
+
io_or_data.rewind if io_or_data.respond_to?(:rewind)
|
28
|
+
response = http_client.request(request)
|
29
|
+
else
|
30
|
+
response = http_client.request(request, io_or_data)
|
31
|
+
end
|
32
|
+
|
33
|
+
response.error! unless response.is_a?(Net::HTTPSuccess)
|
34
|
+
raise "Got a HTTP #{response.code} when trying to store content - should always be 201" unless response.code.to_i == 201
|
35
|
+
raise "No location was returned when trying to store content - should always be given" unless response['location']
|
36
|
+
response['location']
|
37
|
+
end
|
38
|
+
|
39
|
+
def load(path, initheader = {}, force_text_encoding: "UTF-8")
|
40
|
+
response = http_client.request_get(path, initheader)
|
41
|
+
response.error! unless response.is_a?(Net::HTTPSuccess)
|
42
|
+
|
43
|
+
if force_text_encoding && response.content_type =~ /text\//
|
44
|
+
[response.body.force_encoding(force_text_encoding), response.content_type]
|
45
|
+
else
|
46
|
+
[response.body, response.content_type]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def stream(path, initheader = {})
|
51
|
+
http_client.request_get(path, initheader) do |response|
|
52
|
+
response.error! unless response.is_a?(Net::HTTPSuccess)
|
53
|
+
response.read_body do |chunk|
|
54
|
+
yield chunk
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/verm/version.rb
ADDED
Binary file
|
Binary file
|
Binary file
|
data/test/verm_test.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'verm/client'
|
4
|
+
require 'byebug' rescue nil
|
5
|
+
|
6
|
+
class TestVerm < Minitest::Test
|
7
|
+
def setup
|
8
|
+
@client = Verm::Client.new(ENV["VERM_TEST_HOSTNAME"] || "localhost")
|
9
|
+
end
|
10
|
+
|
11
|
+
def fixture_file_path(filename)
|
12
|
+
File.join(File.dirname(__FILE__), 'fixtures', filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_stores_content_and_returns_location
|
16
|
+
assert_equal "/test/files/F0/ZdYVIlyqOiCKtR_oQF_9y8G8_9qAWhR9Fw5hzK8UM.txt",
|
17
|
+
@client.store("/test/files", "this is a test", "text/plain")
|
18
|
+
|
19
|
+
assert_equal "/test/files/F0/ZdYVIlyqOiCKtR_oQF_9y8G8_9qAWhR9Fw5hzK8UM.txt",
|
20
|
+
@client.store("/test/files/", "this is a test", "text/plain")
|
21
|
+
|
22
|
+
assert_equal "/test/files/F0/ZdYVIlyqOiCKtR_oQF_9y8G8_9qAWhR9Fw5hzK8UM",
|
23
|
+
@client.store("/test/files", "this is a test", "application/octet-stream")
|
24
|
+
|
25
|
+
assert_equal "/test/files/SL/VHO4KGrhBRAAjinYUEdqilkOrS4JD6akWSeJb5Tra.txt",
|
26
|
+
@client.store("/test/files", "this is a test\n", "text/plain")
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_stores_files_and_returns_location
|
30
|
+
File.open fixture_file_path("binary_file") do |f|
|
31
|
+
assert_equal "/bins/IF/P8unS2JIuR6_UZI5pZ0lxWHhfvR2ocOcRAma_lEiA",
|
32
|
+
@client.store("/bins/", f, "application/octet-stream")
|
33
|
+
|
34
|
+
assert_equal "/bins/IF/P8unS2JIuR6_UZI5pZ0lxWHhfvR2ocOcRAma_lEiA.png",
|
35
|
+
@client.store("/bins/", f, "image/png")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_stores_compressed_files_and_returns_location_from_uncompressed_content
|
40
|
+
File.open fixture_file_path("binary_file.gz") do |f|
|
41
|
+
# note the hashes are the same here as the uncompressed file above
|
42
|
+
assert_equal "/bins/IF/P8unS2JIuR6_UZI5pZ0lxWHhfvR2ocOcRAma_lEiA",
|
43
|
+
@client.store("/bins/", f, "application/octet-stream", encoding: 'gzip')
|
44
|
+
|
45
|
+
assert_equal "/bins/IF/P8unS2JIuR6_UZI5pZ0lxWHhfvR2ocOcRAma_lEiA.png",
|
46
|
+
@client.store("/bins/", f, "image/png", encoding: 'gzip')
|
47
|
+
end
|
48
|
+
|
49
|
+
File.open fixture_file_path("large_compressed_csv_file.gz") do |f|
|
50
|
+
assert_equal "/csvs/VP/YY9KXv6cc6XksLTHOQJywCHnzyQDCd7Xh7HHUO2hd.csv",
|
51
|
+
@client.store("/csvs/", f, "text/csv", encoding: 'gzip')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_loads_content_and_type
|
56
|
+
content, type = "this is a test", "text/plain"
|
57
|
+
assert_equal [content, type],
|
58
|
+
@client.load(@client.store("/test/files_to_load", content, type))
|
59
|
+
|
60
|
+
content, type = File.binread(fixture_file_path("binary_file")), "application/octet-stream"
|
61
|
+
assert_equal [content, type],
|
62
|
+
@client.load(@client.store("/test/files_to_load", content, type))
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_loads_and_uncompresses_compressed_content_and_type
|
66
|
+
compressed_content, type = File.binread(fixture_file_path("binary_file.gz")), "application/octet-stream"
|
67
|
+
uncompressed_content = File.binread(fixture_file_path("binary_file"))
|
68
|
+
|
69
|
+
assert_equal [uncompressed_content, type],
|
70
|
+
@client.load(@client.store("/test/compressed", compressed_content, type, encoding: 'gzip'))
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_optionally_doesnt_uncompress_compressed_content
|
74
|
+
compressed_content, type = File.binread(fixture_file_path("binary_file.gz")), "application/octet-stream"
|
75
|
+
|
76
|
+
assert_equal [compressed_content, type],
|
77
|
+
@client.load(@client.store("/test/compressed", compressed_content, type, encoding: 'gzip'), 'Accept-Encoding' => 'gzip')
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_marks_loaded_text_as_utf_8_by_default
|
81
|
+
compressed_content, type = File.binread(fixture_file_path("large_compressed_csv_file.gz")), "text/csv"
|
82
|
+
uncompressed_content = Zlib::GzipReader.new(StringIO.new(compressed_content)).read
|
83
|
+
|
84
|
+
assert_equal [uncompressed_content, type],
|
85
|
+
@client.load(@client.store("/test/compressed", compressed_content, type, encoding: 'gzip'))
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_optionally_doesnt_mark_loaded_text_as_anything
|
89
|
+
compressed_content, type = File.binread(fixture_file_path("large_compressed_csv_file.gz")), "text/csv"
|
90
|
+
uncompressed_content = Zlib::GzipReader.new(StringIO.new(compressed_content)).read.force_encoding("ASCII-8BIT")
|
91
|
+
|
92
|
+
assert_equal [uncompressed_content, type],
|
93
|
+
@client.load(@client.store("/test/compressed", compressed_content, type, encoding: 'gzip'), force_text_encoding: nil)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_streams_content
|
97
|
+
compressed_content, type = File.binread(fixture_file_path("large_compressed_csv_file.gz")), "application/octet-stream"
|
98
|
+
uncompressed_content = Zlib::GzipReader.new(StringIO.new(compressed_content)).read.force_encoding("ASCII-8BIT")
|
99
|
+
|
100
|
+
result = ""
|
101
|
+
chunks = 0
|
102
|
+
@client.stream(@client.store("/test/compressed", uncompressed_content, type)) do |chunk|
|
103
|
+
result << chunk
|
104
|
+
chunks += 1
|
105
|
+
end
|
106
|
+
assert_equal uncompressed_content, result
|
107
|
+
assert chunks > 1, "should have been given the content in multiple chunks"
|
108
|
+
end
|
109
|
+
end
|
data/verm.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/verm/version', __FILE__)
|
3
|
+
|
4
|
+
spec = Gem::Specification.new do |gem|
|
5
|
+
gem.name = 'verm-client'
|
6
|
+
gem.version = Verm::VERSION
|
7
|
+
gem.license = "MIT"
|
8
|
+
gem.summary = "Tiny Ruby HTTP client for the Verm immutable, WORM filestore."
|
9
|
+
gem.description = <<-EOF
|
10
|
+
Adds one-line methods for storing files in Verm and retrieving them again.
|
11
|
+
EOF
|
12
|
+
gem.has_rdoc = false
|
13
|
+
gem.author = "Will Bryant"
|
14
|
+
gem.email = "will.bryant@gmail.com"
|
15
|
+
gem.homepage = "http://github.com/willbryant/verm-client-ruby"
|
16
|
+
|
17
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
gem.files = `git ls-files`.split("\n")
|
19
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
gem.require_path = "lib"
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: verm-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Will Bryant
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-11 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |
|
14
|
+
Adds one-line methods for storing files in Verm and retrieving them again.
|
15
|
+
email: will.bryant@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- MIT-LICENSE
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- lib/verm.rb
|
25
|
+
- lib/verm/client.rb
|
26
|
+
- lib/verm/version.rb
|
27
|
+
- test/fixtures/binary_file
|
28
|
+
- test/fixtures/binary_file.gz
|
29
|
+
- test/fixtures/large_compressed_csv_file.gz
|
30
|
+
- test/verm_test.rb
|
31
|
+
- verm.gemspec
|
32
|
+
homepage: http://github.com/willbryant/verm-client-ruby
|
33
|
+
licenses:
|
34
|
+
- MIT
|
35
|
+
metadata: {}
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 2.2.2
|
53
|
+
signing_key:
|
54
|
+
specification_version: 4
|
55
|
+
summary: Tiny Ruby HTTP client for the Verm immutable, WORM filestore.
|
56
|
+
test_files:
|
57
|
+
- test/fixtures/binary_file
|
58
|
+
- test/fixtures/binary_file.gz
|
59
|
+
- test/fixtures/large_compressed_csv_file.gz
|
60
|
+
- test/verm_test.rb
|