kurosawa 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +54 -5
- data/exe/kurosawa +4 -0
- data/lib/kurosawa.rb +1 -3
- data/lib/kurosawa/connection.rb +4 -0
- data/lib/kurosawa/database.rb +205 -0
- data/lib/kurosawa/filesystems.rb +29 -0
- data/lib/kurosawa/filesystems/base.rb +25 -0
- data/lib/kurosawa/filesystems/local.rb +59 -0
- data/lib/kurosawa/filesystems/s3.rb +72 -0
- data/lib/kurosawa/version.rb +1 -1
- metadata +69 -10
- data/.gitignore +0 -9
- data/.rspec +0 -2
- data/.travis.yml +0 -5
- data/Rakefile +0 -6
- data/kurosawa.gemspec +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14e1940ade23b020c48dd0ea923424bf56fafae2
|
4
|
+
data.tar.gz: 325c412026e1c1efde785a888b8e70254f7ba59b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d4dd6523104e8d90f51c5cdae0998ca417de04e7b81eb6328be73dc4309145f50a17bdff2cedc291afa2dd4e60ae8e5aecef1fb3ff09ffe9af73e797969f527
|
7
|
+
data.tar.gz: ac744719d7b169a2f8811712c3d7f72c3c56583fa1590ef9c30e2adb56b55703866c58f99fe4b422b1a5c0ac62cef31f6973ebb19d7cdd097f00ac97e82a1d37
|
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
#
|
1
|
+
# kurosawa.rb
|
2
2
|
|
3
|
-
|
3
|
+
![Kurosawa Ruby](https://github.com/astrobunny/kurosawa.rb/raw/master/docs/images/kurosawa-ruby.jpg)
|
4
4
|
|
5
|
-
|
5
|
+
A RESTful JSON-based database for eventually-consistent filesystem backends. Uses the REST path to determine object hierarchy.
|
6
|
+
|
7
|
+
# THIS DATABASE IS STILL IN ALPHA
|
6
8
|
|
7
9
|
## Installation
|
8
10
|
|
@@ -22,7 +24,54 @@ Or install it yourself as:
|
|
22
24
|
|
23
25
|
## Usage
|
24
26
|
|
25
|
-
|
27
|
+
### On your local environment
|
28
|
+
|
29
|
+
Run the server
|
30
|
+
|
31
|
+
```
|
32
|
+
KUROSAWA_FILESYSTEM=file://fs/db bundle exec kurosawa
|
33
|
+
```
|
34
|
+
|
35
|
+
### With a docker container
|
36
|
+
|
37
|
+
```
|
38
|
+
docker run -ti -p4567:4567 astrobunny/kurosawa.rb
|
39
|
+
```
|
40
|
+
|
41
|
+
### Try it out!
|
42
|
+
|
43
|
+
Send it REST commands! (Here I am using resty)
|
44
|
+
|
45
|
+
```
|
46
|
+
$ GET /
|
47
|
+
null
|
48
|
+
$ PUT / '{"a": 7, "b": {"e":[100,200,300]} }'
|
49
|
+
{"a":"7","b":{"e":["300","200","100"]}}
|
50
|
+
$ GET /
|
51
|
+
{"a":"7","b":{"e":["300","200","100"]}}
|
52
|
+
$ GET /a/b
|
53
|
+
null
|
54
|
+
$ GET /a
|
55
|
+
"7"
|
56
|
+
$ GET /b
|
57
|
+
{"e":["300","200","100"]}
|
58
|
+
$ GET /b/e
|
59
|
+
["300","200","100"]
|
60
|
+
$ PATCH / '{"c": "Idols"}'
|
61
|
+
{"a":"7","b":{"e":["300","200","100"]},"c":"Idols"}
|
62
|
+
$ GET /c
|
63
|
+
"Idols"
|
64
|
+
$ DELETE /b/e
|
65
|
+
null
|
66
|
+
$ GET /
|
67
|
+
{"a":"7","b":{},"c":"Idols"}
|
68
|
+
$ PUT /c '{}'
|
69
|
+
{}
|
70
|
+
$ PUT /c '{"5": "a"}'
|
71
|
+
{"5":"a"}
|
72
|
+
|
73
|
+
```
|
74
|
+
|
26
75
|
|
27
76
|
## Development
|
28
77
|
|
@@ -32,5 +81,5 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
81
|
|
33
82
|
## Contributing
|
34
83
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
84
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/astrobunny/kurosawa.rb.
|
36
85
|
|
data/exe/kurosawa
ADDED
data/lib/kurosawa.rb
CHANGED
@@ -0,0 +1,205 @@
|
|
1
|
+
require "sinatra/base"
|
2
|
+
require "sinatra/reloader"
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
# filesystems
|
6
|
+
require "kurosawa/filesystems"
|
7
|
+
|
8
|
+
module Kurosawa
|
9
|
+
class Database < ::Sinatra::Base
|
10
|
+
|
11
|
+
set :bind, '0.0.0.0'
|
12
|
+
configure :development do
|
13
|
+
register Sinatra::Reloader
|
14
|
+
end
|
15
|
+
|
16
|
+
filesystem = ENV["KUROSAWA_FILESYSTEM"] || "file://~/.kurosawa"
|
17
|
+
|
18
|
+
set :filesystem, Filesystem.instantiate(filesystem)
|
19
|
+
|
20
|
+
def sanitize_path(path)
|
21
|
+
match = /^\/[a-z0-9\-_\/]*$/i.match(URI.unescape(path))
|
22
|
+
if match
|
23
|
+
match.to_s.sub(/\/+$/, "")
|
24
|
+
else
|
25
|
+
p URI.unescape(path)
|
26
|
+
halt 400
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def sanitize_body(body)
|
31
|
+
begin
|
32
|
+
JSON.parse(body)
|
33
|
+
rescue => e
|
34
|
+
puts e
|
35
|
+
halt 400
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def random_key
|
40
|
+
SecureRandom.hex(4)
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_property(fs, path)
|
44
|
+
property_entries = fs.ls("#{path}/$")
|
45
|
+
if property_entries.length == 0
|
46
|
+
nil
|
47
|
+
elsif property_entries.length == 1
|
48
|
+
JSON.parse(fs.get(property_entries[0]), symbolize_names: true)
|
49
|
+
else
|
50
|
+
# conflict
|
51
|
+
raise "TODO get_property handle conflict"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_property(fs, path, type:)
|
56
|
+
puts "set property: #{path}"
|
57
|
+
property_entries = fs.ls("#{path}/$")
|
58
|
+
p property_entries
|
59
|
+
if property_entries.length > 0
|
60
|
+
property_entries.each do |x|
|
61
|
+
fs.del(x)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
fs.put("#{path}/$#{random_key}", {type: type}.to_json)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def read(fs, path, params)
|
69
|
+
|
70
|
+
puts "read: path=#{path.inspect}"
|
71
|
+
prop = get_property(fs, path)
|
72
|
+
if prop == nil
|
73
|
+
nil
|
74
|
+
elsif prop[:type] == "object"
|
75
|
+
res = {}
|
76
|
+
|
77
|
+
inner_entries = fs.ls("#{path}")
|
78
|
+
.select{ |x| /^\/\$/.match(x) == nil }
|
79
|
+
.map{ |x| x.sub(/\/[^\/]+$/, "") }
|
80
|
+
.map{ |x| match = /(?<first>^\/[^\/]+)/.match(x.sub(/^#{path}/, "")); match[:first] if match }
|
81
|
+
.select{ |x| x != nil}
|
82
|
+
.uniq
|
83
|
+
|
84
|
+
puts "read: object: inner: #{fs.ls("#{path}").inspect}"
|
85
|
+
puts "read: object: inner: #{inner_entries.inspect}"
|
86
|
+
|
87
|
+
inner_entries.each do |x|
|
88
|
+
res[x[1..-1]] = read(fs, path + x, params)
|
89
|
+
end
|
90
|
+
|
91
|
+
res
|
92
|
+
|
93
|
+
elsif prop[:type] == "array"
|
94
|
+
inner_entries = fs.ls("#{path}")
|
95
|
+
.select{ |x| /\/\$/.match(x) == nil }
|
96
|
+
.map{ |x| match = /(?<first>^\/[^\/]+)/.match(x.sub(/^#{path}/, "")); match[:first] if match }
|
97
|
+
.select{ |x| x != nil}
|
98
|
+
.uniq
|
99
|
+
|
100
|
+
puts "read: array: #{inner_entries.inspect}"
|
101
|
+
|
102
|
+
inner_entries.map do |x|
|
103
|
+
read(fs, path + x, params)
|
104
|
+
end
|
105
|
+
|
106
|
+
else
|
107
|
+
inner_entries = fs.ls("#{path}")
|
108
|
+
.select{ |x| /\/\$/.match(x) == nil }
|
109
|
+
|
110
|
+
puts "read: string: #{inner_entries.inspect}"
|
111
|
+
|
112
|
+
if inner_entries.length == 1
|
113
|
+
JSON.parse(fs.get(inner_entries[0]), symbolize_names: true)[:value]
|
114
|
+
elsif inner_entries.length == 0
|
115
|
+
nil
|
116
|
+
else
|
117
|
+
{"$conflict": inner_entries.map{|x| JSON.parse(fs.get(x), symbolize_names: true) }}
|
118
|
+
#raise "read conflict at #{path} #{inner_entries.inspect}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def write(fs, path, body)
|
124
|
+
|
125
|
+
puts "write: path=#{path.inspect}"
|
126
|
+
|
127
|
+
if body.is_a? Hash
|
128
|
+
set_property(fs, path, type: "object")
|
129
|
+
body.each do |k,v|
|
130
|
+
write(fs, "#{path}/#{k}", v)
|
131
|
+
end
|
132
|
+
|
133
|
+
elsif body.is_a? Array
|
134
|
+
set_property(fs, path, type: "array")
|
135
|
+
body.each do |value|
|
136
|
+
write(fs, "#{path}/#{random_key}", value)
|
137
|
+
end
|
138
|
+
|
139
|
+
else
|
140
|
+
existing_entries = fs.ls("#{path}")
|
141
|
+
|
142
|
+
if existing_entries.length > 0
|
143
|
+
existing_entries.each do |x|
|
144
|
+
fs.del(x)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
set_property(fs, path, type: "string")
|
148
|
+
fs.put("#{path}/#{random_key}", {value: body.to_s}.to_json)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def delete(fs, path)
|
153
|
+
inner_entries = fs.ls("#{path}")
|
154
|
+
|
155
|
+
puts "delete: #{inner_entries.inspect}"
|
156
|
+
|
157
|
+
inner_entries.each do |x|
|
158
|
+
fs.del(x)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
get "*" do
|
163
|
+
path = sanitize_path(request.path)
|
164
|
+
x = read(settings.filesystem, path, params)
|
165
|
+
status 404 if x == nil
|
166
|
+
x.to_json
|
167
|
+
end
|
168
|
+
|
169
|
+
post "*" do
|
170
|
+
path = sanitize_path(request.path)
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
put "*" do
|
175
|
+
path = sanitize_path(request.path)
|
176
|
+
delete(settings.filesystem, path)
|
177
|
+
write(settings.filesystem, path, sanitize_body(request.body.read))
|
178
|
+
read(settings.filesystem, path, params).to_json
|
179
|
+
end
|
180
|
+
|
181
|
+
patch "*" do
|
182
|
+
path = sanitize_path(request.path)
|
183
|
+
write(settings.filesystem, path, sanitize_body(request.body.read))
|
184
|
+
read(settings.filesystem, path, params).to_json
|
185
|
+
end
|
186
|
+
|
187
|
+
delete "*" do
|
188
|
+
path = sanitize_path(request.path)
|
189
|
+
delete(settings.filesystem, path)
|
190
|
+
read(settings.filesystem, path, params).to_json
|
191
|
+
end
|
192
|
+
|
193
|
+
head "*" do
|
194
|
+
path = sanitize_path(request.path)
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
options "*" do
|
199
|
+
path = sanitize_path(request.path)
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
require "kurosawa/filesystems/local"
|
3
|
+
require "kurosawa/filesystems/s3"
|
4
|
+
|
5
|
+
require "uri"
|
6
|
+
|
7
|
+
module Kurosawa
|
8
|
+
class Filesystem
|
9
|
+
def self.instantiate(fs)
|
10
|
+
if fs.start_with?("file://")
|
11
|
+
Kurosawa::Filesystems::Local.new(fs.sub("file://", ""))
|
12
|
+
elsif fs.start_with?("s3://") or fs.start_with?("s3http://") or fs.start_with?("s3https://")
|
13
|
+
|
14
|
+
url = URI.parse(fs);
|
15
|
+
tokens = url.userinfo.split(":")
|
16
|
+
|
17
|
+
Kurosawa::Filesystems::S3.new(
|
18
|
+
access_key_id:"#{tokens[0]}",
|
19
|
+
secret_access_key:"#{tokens[1]}",
|
20
|
+
region:"#{tokens[2]}",
|
21
|
+
bucket:url.scheme == "s3" ? url.host : "",
|
22
|
+
endpoint:url.scheme == "s3" ? nil : "#{url.scheme.sub("s3","")}://#{url.host}:#{url.port}",
|
23
|
+
force_path_style: url.scheme != "s3")
|
24
|
+
else
|
25
|
+
raise "Unknown filesystem"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module Kurosawa::Filesystems
|
3
|
+
class Base
|
4
|
+
def ls(prefix)
|
5
|
+
[]
|
6
|
+
end
|
7
|
+
|
8
|
+
def get(key)
|
9
|
+
""
|
10
|
+
end
|
11
|
+
|
12
|
+
def put(key, value)
|
13
|
+
end
|
14
|
+
|
15
|
+
def del(key)
|
16
|
+
end
|
17
|
+
|
18
|
+
def exists(key)
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def cleanup!
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'kurosawa/filesystems/base'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Kurosawa::Filesystems
|
5
|
+
class Local < Base
|
6
|
+
|
7
|
+
def initialize(root_path)
|
8
|
+
@root_path = File.expand_path(root_path)
|
9
|
+
FileUtils.mkdir_p(@root_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def root_path
|
13
|
+
@root_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def path(key)
|
17
|
+
File.join(@root_path, key)
|
18
|
+
end
|
19
|
+
|
20
|
+
def ls(prefix)
|
21
|
+
puts "fs: ls #{prefix}"
|
22
|
+
(Dir["#{@root_path}/#{prefix}*"] + Dir["#{@root_path}/#{prefix}/**/*"]).
|
23
|
+
select{|x| File.file?(x)}.
|
24
|
+
map{|x| x.sub(/^#{root_path}/, "").
|
25
|
+
gsub(/\/+/, "/")}.
|
26
|
+
uniq
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def get(key)
|
31
|
+
puts "fs: get #{path(key)}"
|
32
|
+
File.read(path(key))
|
33
|
+
end
|
34
|
+
|
35
|
+
def put(key, value)
|
36
|
+
puts "fs: put #{path(key)}"
|
37
|
+
FileUtils.mkdir_p(File.dirname(path(key)))
|
38
|
+
File.write(path(key), value)
|
39
|
+
end
|
40
|
+
|
41
|
+
def del(key)
|
42
|
+
puts "fs: delete #{path(key)}"
|
43
|
+
File.delete(path(key)) if File.file?(path(key))
|
44
|
+
end
|
45
|
+
|
46
|
+
def exists(key)
|
47
|
+
puts "fs: exists #{path(key)}"
|
48
|
+
File.exists?(path(key)) and File.file?(path(key))
|
49
|
+
end
|
50
|
+
|
51
|
+
def cleanup!
|
52
|
+
Dir['#{@root_path}**/*'].
|
53
|
+
select { |d| File.directory? d }.
|
54
|
+
select { |d| (Dir.entries(d) - %w[ . .. ]).empty? }.
|
55
|
+
each { |d| Dir.rmdir d }
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'kurosawa/filesystems/base'
|
2
|
+
require 'uri'
|
3
|
+
require 'aws-sdk'
|
4
|
+
|
5
|
+
module Kurosawa::Filesystems
|
6
|
+
class S3 < Base
|
7
|
+
|
8
|
+
def initialize(access_key_id:,secret_access_key:,region:,endpoint:,bucket:,force_path_style:false)
|
9
|
+
|
10
|
+
options = {
|
11
|
+
:access_key_id => URI.encode(access_key_id),
|
12
|
+
:secret_access_key => URI.decode(secret_access_key),
|
13
|
+
:region => region,
|
14
|
+
:force_path_style => force_path_style
|
15
|
+
}
|
16
|
+
options[:endpoint] = endpoint if endpoint
|
17
|
+
|
18
|
+
@s3 = Aws::S3::Client.new(options)
|
19
|
+
@bucket_name = bucket
|
20
|
+
@bucket = Aws::S3::Bucket.new(bucket, client: @s3)
|
21
|
+
end
|
22
|
+
|
23
|
+
def ls(prefix)
|
24
|
+
prefix.gsub!(/^\/+/, "")
|
25
|
+
puts "s3:ls #{prefix}"
|
26
|
+
result = []
|
27
|
+
next_marker = nil
|
28
|
+
loop do
|
29
|
+
options = {
|
30
|
+
bucket: @bucket_name,
|
31
|
+
marker: next_marker
|
32
|
+
}
|
33
|
+
|
34
|
+
options[:prefix] = prefix if prefix.length != 0
|
35
|
+
|
36
|
+
resp = @s3.list_objects(options);
|
37
|
+
result += resp.contents.map { |x| "/#{x.key}" }
|
38
|
+
break if resp.next_marker == nil
|
39
|
+
next_marker = resp.next_marker
|
40
|
+
end
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def get(key)
|
45
|
+
key.gsub!(/^\/+/, "")
|
46
|
+
puts "s3:get #{key}"
|
47
|
+
resp = @s3.get_object(bucket: @bucket_name, key: key)
|
48
|
+
resp.body.read
|
49
|
+
end
|
50
|
+
|
51
|
+
def put(key, value)
|
52
|
+
key.gsub!(/^\/+/, "")
|
53
|
+
puts "s3:put #{key}"
|
54
|
+
@s3.put_object(bucket: @bucket_name, key: key, body: value)
|
55
|
+
end
|
56
|
+
|
57
|
+
def del(key)
|
58
|
+
key.gsub!(/^\/+/, "")
|
59
|
+
puts "s3:del #{key}"
|
60
|
+
@s3.delete_object(bucket: @bucket_name, key: key)
|
61
|
+
end
|
62
|
+
|
63
|
+
def exists(key)
|
64
|
+
key.gsub!(/^\/+/, "")
|
65
|
+
puts "s3:exists #{key}"
|
66
|
+
@bucket.objects[key].exists?
|
67
|
+
end
|
68
|
+
|
69
|
+
def cleanup!
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/kurosawa/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kurosawa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- astrobunny
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,25 +52,84 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: fakes3
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sinatra
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.4'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.4'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sinatra-contrib
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: aws-sdk
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.4.4
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.4.4
|
55
111
|
description: Tribute to Kurosawa Ruby
|
56
112
|
email:
|
57
113
|
- admin@astrobunny.com
|
58
|
-
executables:
|
114
|
+
executables:
|
115
|
+
- kurosawa
|
59
116
|
extensions: []
|
60
117
|
extra_rdoc_files: []
|
61
118
|
files:
|
62
|
-
- ".gitignore"
|
63
|
-
- ".rspec"
|
64
|
-
- ".travis.yml"
|
65
119
|
- Gemfile
|
66
120
|
- README.md
|
67
|
-
- Rakefile
|
68
121
|
- bin/console
|
69
122
|
- bin/setup
|
70
|
-
- kurosawa
|
123
|
+
- exe/kurosawa
|
71
124
|
- lib/kurosawa.rb
|
125
|
+
- lib/kurosawa/connection.rb
|
126
|
+
- lib/kurosawa/database.rb
|
127
|
+
- lib/kurosawa/filesystems.rb
|
128
|
+
- lib/kurosawa/filesystems/base.rb
|
129
|
+
- lib/kurosawa/filesystems/local.rb
|
130
|
+
- lib/kurosawa/filesystems/s3.rb
|
72
131
|
- lib/kurosawa/version.rb
|
73
|
-
homepage: https://github.com/astrobunny/kurosawa
|
132
|
+
homepage: https://github.com/astrobunny/kurosawa.rb
|
74
133
|
licenses: []
|
75
134
|
metadata:
|
76
135
|
allowed_push_host: https://rubygems.org
|
@@ -90,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
149
|
version: '0'
|
91
150
|
requirements: []
|
92
151
|
rubyforge_project:
|
93
|
-
rubygems_version: 2.
|
152
|
+
rubygems_version: 2.4.8
|
94
153
|
signing_key:
|
95
154
|
specification_version: 4
|
96
155
|
summary: kurosawa.rb
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
data/Rakefile
DELETED
data/kurosawa.gemspec
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'kurosawa/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "kurosawa"
|
8
|
-
spec.version = Kurosawa::VERSION
|
9
|
-
spec.authors = ["astrobunny"]
|
10
|
-
spec.email = ["admin@astrobunny.com"]
|
11
|
-
|
12
|
-
spec.summary = %q{kurosawa.rb}
|
13
|
-
spec.description = %q{Tribute to Kurosawa Ruby}
|
14
|
-
spec.homepage = "https://github.com/astrobunny/kurosawa"
|
15
|
-
|
16
|
-
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
-
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
-
if spec.respond_to?(:metadata)
|
19
|
-
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
20
|
-
else
|
21
|
-
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
22
|
-
end
|
23
|
-
|
24
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
-
spec.bindir = "exe"
|
26
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
-
spec.require_paths = ["lib"]
|
28
|
-
|
29
|
-
spec.add_development_dependency "bundler", "~> 1.12"
|
30
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
32
|
-
end
|