bfs-gs 0.3.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/bfs-gs.gemspec +22 -0
- data/lib/bfs/bucket/gs.rb +113 -0
- data/lib/bfs/gs.rb +1 -0
- data/spec/bfs/bucket/gs_spec.rb +53 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 637ee81c056b08e88dea4194468a7cf88c749a93d5c74a76d53a2ebd33bbd538
|
4
|
+
data.tar.gz: 45de2c2033328feb46e7695a0a79a979bf7f6fdfa2332691098db1b9832329e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a38e3c19acceba3f87c7db63414b67db0c249a977a2045d0a214467b756a8ebb4f5e9d12247868f81b8e3afb9564bb1db848f434ad9ab7478a722adc0e64529
|
7
|
+
data.tar.gz: e35c73ffcae6f8975aa1fb56df86b85e3a47550be62536981f38c70b3bfcf74648c95a548fb45f5a790325ba481265c4d64656c6b3b6ef601dd768081b5c7fa6
|
data/bfs-gs.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'bfs-gs'
|
3
|
+
s.version = File.read(File.expand_path('../.version', __dir__)).strip
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
|
6
|
+
s.licenses = ['Apache-2.0']
|
7
|
+
s.summary = 'GS bucket adapter for bfs'
|
8
|
+
s.description = 'https://github.com/bsm/bfs.rb'
|
9
|
+
|
10
|
+
s.authors = ['Dimitrij Denissenko']
|
11
|
+
s.email = 'dimitrij@blacksquaremedia.com'
|
12
|
+
s.homepage = 'https://github.com/bsm/bfs.rb'
|
13
|
+
|
14
|
+
s.executables = []
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
s.required_ruby_version = '>= 2.2.0'
|
19
|
+
|
20
|
+
s.add_dependency 'bfs', s.version
|
21
|
+
s.add_dependency 'google-cloud-storage'
|
22
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'bfs'
|
2
|
+
require 'google/cloud/storage'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module BFS
|
6
|
+
module Bucket
|
7
|
+
# GS buckets are operating on Google Cloud Storage
|
8
|
+
class GS < Abstract
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# Initializes a new GoogleCloudStorage bucket.
|
12
|
+
#
|
13
|
+
# @param [String] name the bucket name.
|
14
|
+
# @param [Hash] opts options.
|
15
|
+
# @option opts [String] :project_id project ID. Defaults to GCP_PROJECT env var. Required.
|
16
|
+
# @option opts [String, Hash, Google::Auth::Credentials] :credentials
|
17
|
+
# the path to the keyfile as a String, the contents of the keyfile as a Hash, or a Google::Auth::Credentials object.
|
18
|
+
# @option opts [Integer] :retries number of times to retry requests. Default: 3.
|
19
|
+
# @option opts [Integer] :timeout request timeout, in seconds.
|
20
|
+
# @option opts [String] :acl set the default ACL.
|
21
|
+
# @option opts [Google::Cloud::Storage] :client custom client.
|
22
|
+
def initialize(name, opts={})
|
23
|
+
opts = opts.dup
|
24
|
+
opts.keys.each do |key|
|
25
|
+
val = opts.delete(key)
|
26
|
+
opts[key.to_sym] = val unless val.nil?
|
27
|
+
end
|
28
|
+
opts[:project_id] ||= ENV['GCP_PROJECT'] || ENV['GCLOUD_PROJECT']
|
29
|
+
|
30
|
+
acl = opts.delete(:acl)
|
31
|
+
client = opts.delete(:client) || Google::Cloud::Storage.new(opts)
|
32
|
+
|
33
|
+
@name = name.to_s
|
34
|
+
@bucket = client.bucket(@name)
|
35
|
+
@bucket.default_acl.send(:"#{acl}!") if @bucket.default_acl.respond_to?(:"#{acl}!")
|
36
|
+
end
|
37
|
+
|
38
|
+
# Lists the contents of a bucket using a glob pattern
|
39
|
+
def ls(pattern='**/*', opts={})
|
40
|
+
Enumerator.new do |y|
|
41
|
+
@bucket.files(opts).each do |file|
|
42
|
+
y << file.name if File.fnmatch?(pattern, file.name, File::FNM_PATHNAME)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Info returns the object info
|
48
|
+
def info(path, _opts={})
|
49
|
+
path = norm_path(path)
|
50
|
+
file = @bucket.file(path)
|
51
|
+
raise BFS::FileNotFound, path unless file
|
52
|
+
|
53
|
+
BFS::FileInfo.new(path, file.size, file.updated_at)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Creates a new file and opens it for writing
|
57
|
+
def create(path, opts={}, &block)
|
58
|
+
path = norm_path(path)
|
59
|
+
temp = BFS::TempWriter.new(path) do |t|
|
60
|
+
File.open(t, binmode: true) do |file|
|
61
|
+
@bucket.create_file(file, path, opts)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
return temp unless block
|
65
|
+
|
66
|
+
begin
|
67
|
+
yield temp
|
68
|
+
ensure
|
69
|
+
temp.close
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Opens an existing file for reading
|
74
|
+
def open(path, opts={}, &block)
|
75
|
+
path = norm_path(path)
|
76
|
+
file = @bucket.file(path)
|
77
|
+
raise BFS::FileNotFound, path unless file
|
78
|
+
|
79
|
+
temp = Tempfile.new(File.basename(path), binmode: true)
|
80
|
+
temp.close
|
81
|
+
file.download temp.path, opts
|
82
|
+
|
83
|
+
File.open(temp.path, binmode: true, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Deletes a file.
|
87
|
+
def rm(path, opts={})
|
88
|
+
path = norm_path(path)
|
89
|
+
file = @bucket.file(path)
|
90
|
+
file.delete(opts) if file
|
91
|
+
end
|
92
|
+
|
93
|
+
# Copies a file.
|
94
|
+
def cp(src, dst, opts={})
|
95
|
+
src = norm_path(src)
|
96
|
+
file = @bucket.file(src)
|
97
|
+
raise BFS::FileNotFound, src unless file
|
98
|
+
|
99
|
+
file.copy(norm_path(dst), opts)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
BFS.register('gs') do |url|
|
106
|
+
params = CGI.parse(url.query.to_s)
|
107
|
+
|
108
|
+
BFS::Bucket::GS.new url.host,
|
109
|
+
project_id: params.key?('project_id') ? params['project_id'].first : nil,
|
110
|
+
acl: params.key?('acl') ? params['acl'].first : nil,
|
111
|
+
timeout: params.key?('timeout') ? params['timeout'].first.to_i : nil,
|
112
|
+
retries: params.key?('retries') ? params['retries'].first.to_i : nil
|
113
|
+
end
|
data/lib/bfs/gs.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bfs/bucket/gs'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe BFS::Bucket::GS do
|
4
|
+
let(:contents) { {} }
|
5
|
+
let(:mock_client) { double Google::Cloud::Storage, bucket: mock_bucket }
|
6
|
+
|
7
|
+
let :mock_bucket do
|
8
|
+
bucket = double Google::Cloud::Storage::Bucket,
|
9
|
+
default_acl: double(Google::Cloud::Storage::Bucket::Acl)
|
10
|
+
allow(bucket).to receive(:create_file) do |io, name, _|
|
11
|
+
contents[name] = double_file(name, io.read)
|
12
|
+
end
|
13
|
+
allow(bucket).to receive(:files) do |_|
|
14
|
+
contents.values
|
15
|
+
end
|
16
|
+
allow(bucket).to receive(:file) do |name|
|
17
|
+
contents[name]
|
18
|
+
end
|
19
|
+
bucket
|
20
|
+
end
|
21
|
+
|
22
|
+
def double_file(name, data)
|
23
|
+
file = double Google::Cloud::Storage::File,
|
24
|
+
name: name,
|
25
|
+
data: data,
|
26
|
+
size: data.bytesize,
|
27
|
+
updated_at: Time.now
|
28
|
+
allow(file).to receive(:download) do |path, _|
|
29
|
+
File.open(path, 'wb') {|f| f.write file.data }
|
30
|
+
end
|
31
|
+
allow(file).to receive(:delete) do |_|
|
32
|
+
contents.delete(file.name)
|
33
|
+
true
|
34
|
+
end
|
35
|
+
allow(file).to receive(:copy) do |dst, _|
|
36
|
+
contents[dst] = double_file(dst, file.data)
|
37
|
+
end
|
38
|
+
file
|
39
|
+
end
|
40
|
+
|
41
|
+
subject { described_class.new 'mock-bucket', client: mock_client }
|
42
|
+
it_behaves_like 'a bucket'
|
43
|
+
|
44
|
+
it 'should resolve from URL' do
|
45
|
+
expect(Google::Cloud::Storage).to receive(:new).with(project_id: 'my-project').and_return(mock_client)
|
46
|
+
expect(mock_client).to receive(:bucket).with('mock-bucket').and_return(mock_bucket)
|
47
|
+
expect(mock_bucket.default_acl).to receive(:private!).with(no_args)
|
48
|
+
|
49
|
+
bucket = BFS.resolve('gs://mock-bucket?acl=private&project_id=my-project')
|
50
|
+
expect(bucket).to be_instance_of(described_class)
|
51
|
+
expect(bucket.name).to eq('mock-bucket')
|
52
|
+
end
|
53
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bfs-gs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dimitrij Denissenko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bfs
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: google-cloud-storage
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: https://github.com/bsm/bfs.rb
|
42
|
+
email: dimitrij@blacksquaremedia.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- bfs-gs.gemspec
|
48
|
+
- lib/bfs/bucket/gs.rb
|
49
|
+
- lib/bfs/gs.rb
|
50
|
+
- spec/bfs/bucket/gs_spec.rb
|
51
|
+
homepage: https://github.com/bsm/bfs.rb
|
52
|
+
licenses:
|
53
|
+
- Apache-2.0
|
54
|
+
metadata: {}
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.2.0
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 2.7.7
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: GS bucket adapter for bfs
|
75
|
+
test_files:
|
76
|
+
- spec/bfs/bucket/gs_spec.rb
|