kurosawa 0.1.0 → 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 +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
|
+

|
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
|