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