bfs 0.6.2 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e9c5b7b27a3bca8975dac3ccce6d99fc3e22a012758adf5a82baceeafd12aa7
4
- data.tar.gz: 930feef7182ef50e2106e8b48f0af0cf388b8cfa8cb39d3bf6a2dc0bb556568f
3
+ metadata.gz: 4851ad3e633d9ba6e2e1533206f9810390ff29959d047916f32004c4432bc282
4
+ data.tar.gz: 9129b8d9d6a87a8a5e97bd45145b4936f07bfd27c6c088bad6797477afcbf795
5
5
  SHA512:
6
- metadata.gz: 496a92c2ac19fb0fb11a4fafbf20db067df87b678dbfea6d90fdf53e8f9088c8b1f059d87a93cd2da3de6a610f033a5ed6dec2eba0cffedad31a76a518130071
7
- data.tar.gz: 56991e1f1088e1b361635ba17b3c235e464bd98e587db34a28e7e7d01c3b60c692b4b508646686a008e38cd731413dfd13174e87fe9b6e135317d24558fbee39
6
+ metadata.gz: 015a5be095930a9f2a4b446809ac4d2684cd4c49ff3b56fc7a28b1f43b2bfe49953625092fcdced43969407d9d40e63eabc6f127fcb58d139d7de55b4b6f98d3
7
+ data.tar.gz: 8a3dcc158679457ba9881a29d47c0e4a1c316b040c2080bba61f80c596f20245125b1071a47c9540f65a588e94cccdf519bf0d975a38693c6b5e89ccee5c9326
@@ -15,5 +15,5 @@ Gem::Specification.new do |s|
15
15
  s.files = `git ls-files`.split("\n")
16
16
  s.test_files = `git ls-files -- spec/*`.split("\n")
17
17
  s.require_paths = ['lib']
18
- s.required_ruby_version = '>= 2.5.0'
18
+ s.required_ruby_version = '>= 2.6.0'
19
19
  end
data/lib/bfs.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'uri'
2
+ require 'cgi'
2
3
 
3
4
  module BFS
4
5
  class FileInfo < Hash
@@ -39,12 +40,16 @@ module BFS
39
40
  end
40
41
  end
41
42
 
42
- def self.resolve(url)
43
+ def self.resolve(url, &block)
43
44
  url = url.is_a?(::URI) ? url.dup : URI.parse(url)
44
45
  rsl = @registry[url.scheme]
45
46
  raise ArgumentError, "Unable to resolve #{url}, scheme #{url.scheme} is not registered" unless rsl
46
47
 
47
- rsl.call(url)
48
+ opts = {}
49
+ CGI.parse(url.query.to_s).each do |key, values|
50
+ opts[key.to_sym] = values.first
51
+ end
52
+ rsl.call(url, opts, block)
48
53
  end
49
54
 
50
55
  def self.norm_path(path)
@@ -59,6 +64,11 @@ module BFS
59
64
  mode = mode.to_i(8) if mode.is_a?(String)
60
65
  mode & 0o000777
61
66
  end
67
+
68
+ def self.defer(obj, method)
69
+ owner = Process.pid
70
+ ObjectSpace.define_finalizer(obj, ->(*) { obj.send(method) if Process.pid == owner })
71
+ end
62
72
  end
63
73
 
64
74
  require 'bfs/helpers'
@@ -3,12 +3,26 @@ module BFS
3
3
  class Blob
4
4
  attr_reader :path
5
5
 
6
+ # Behaves like new, but accepts an optional block.
7
+ # If a block is given, blobs are automatically closed after the block is yielded.
8
+ def self.open(url)
9
+ blob = new(url)
10
+ begin
11
+ yield blob
12
+ ensure
13
+ blob.close
14
+ end if block_given?
15
+ blob
16
+ end
17
+
6
18
  def initialize(url)
7
19
  url = url.is_a?(::URI) ? url.dup : URI.parse(url)
8
20
  @path = BFS.norm_path(url.path)
9
21
 
10
22
  url.path = '/'
11
23
  @bucket = BFS.resolve(url)
24
+
25
+ BFS.defer(self, :close)
12
26
  end
13
27
 
14
28
  # Info returns the blob info.
@@ -34,7 +48,7 @@ module BFS
34
48
 
35
49
  # Shortcut method to read the contents of the blob.
36
50
  def read(**opts)
37
- open(**opts, &:read)
51
+ self.open(**opts, &:read)
38
52
  end
39
53
 
40
54
  # Shortcut method to write data to blob.
@@ -3,11 +3,35 @@ require 'bfs'
3
3
  module BFS
4
4
  module Bucket
5
5
  class Abstract
6
+ attr_reader :encoding, :perm
7
+
8
+ # Behaves like new, but accepts an optional block.
9
+ # If a block is given, buckets are automatically closed after the block is yielded.
10
+ def self.open(*args, **opts)
11
+ bucket = new(*args, **opts)
12
+ begin
13
+ yield bucket
14
+ ensure
15
+ bucket.close
16
+ end if block_given?
17
+ bucket
18
+ end
19
+
6
20
  # Initializes a new bucket
7
21
  # @param [Hash] opts options
8
22
  # @option opts [String] :encoding Custom encoding. Default: Encoding.default_external.
9
- def initialize(encoding: Encoding.default_external, **_opts)
23
+ # @option opts [Integer] :perm optional file permissions. Default: 0600.
24
+ def initialize(encoding: Encoding.default_external, perm: nil, **_opts)
10
25
  @encoding = encoding
26
+
27
+ case perm
28
+ when Integer
29
+ @perm = perm
30
+ when String
31
+ @perm = perm.to_i(8)
32
+ end
33
+
34
+ BFS.defer(self, :close)
11
35
  end
12
36
 
13
37
  # Lists the contents of a bucket using a glob pattern
@@ -41,7 +65,7 @@ module BFS
41
65
  # @param [String] path The path to read from.
42
66
  # @param [Hash] opts Additional options, see #open.
43
67
  def read(path, **opts)
44
- open(path, **opts, &:read)
68
+ self.open(path, **opts, &:read)
45
69
  end
46
70
 
47
71
  # Shortcut method to write data to path
@@ -58,7 +82,7 @@ module BFS
58
82
  # @param [String] src The source path.
59
83
  # @param [String] dst The destination path.
60
84
  def cp(src, dst, **opts)
61
- open(src, **opts) do |r|
85
+ self.open(src, **opts) do |r|
62
86
  create(dst, **opts) do |w|
63
87
  IO.copy_stream(r, w)
64
88
  end
@@ -38,12 +38,11 @@ module BFS
38
38
  # @param [Hash] opts Additional options.
39
39
  # @option opts [String] :encoding Custom encoding.
40
40
  # @option opts [Integer] :perm Custom file permission, default: 0600.
41
- def create(path, encoding: nil, perm: nil, **_opts, &block)
41
+ def create(path, encoding: self.encoding, perm: self.perm, **_opts, &block)
42
42
  full = @root.join(norm_path(path))
43
43
  FileUtils.mkdir_p(full.dirname.to_s)
44
44
 
45
- enc = encoding || @encoding
46
- temp = BFS::TempWriter.new(full, encoding: enc, perm: perm) {|t| FileUtils.mv t, full.to_s }
45
+ temp = BFS::TempWriter.new(full, encoding: encoding, perm: perm) {|t| FileUtils.mv t, full.to_s }
47
46
  return temp unless block
48
47
 
49
48
  begin
@@ -103,7 +102,7 @@ module BFS
103
102
  end
104
103
  end
105
104
 
106
- BFS.register('file') do |url|
105
+ BFS.register('file') do |url, opts, block|
107
106
  parts = [url.host, url.path].compact
108
- BFS::Bucket::FS.new File.join(*parts)
107
+ BFS::Bucket::FS.open(File.join(*parts), **opts, &block)
109
108
  end
@@ -42,11 +42,11 @@ module BFS
42
42
  # @option opts [String] :encoding Custom encoding.
43
43
  # @option opts [String] :content_type Custom content type.
44
44
  # @option opts [Hash] :metadata Metadata key-value pairs.
45
- def create(path, **opts, &block)
45
+ def create(path, encoding: self.encoding, content_type: nil, metadata: nil, **_opts, &block)
46
46
  io = StringIO.new
47
- io.set_encoding(opts.delete(:encoding) || @encoding)
47
+ io.set_encoding(encoding)
48
48
 
49
- entry = Entry.new(io, Time.now, opts.delete(:content_type), norm_meta(opts.delete(:metadata)))
49
+ entry = Entry.new(io, Time.now, content_type, norm_meta(metadata))
50
50
  @files[norm_path(path)] = entry
51
51
  return io unless block
52
52
 
@@ -0,0 +1 @@
1
+ require 'bfs/bucket/fs'
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe BFS::Bucket::Abstract do
4
+ it 'should open with a block' do
5
+ sub_class = Class.new(described_class) do
6
+ def close
7
+ @closed = true
8
+ end
9
+
10
+ def closed?
11
+ @closed == true
12
+ end
13
+ end
14
+
15
+ bucket = nil
16
+ sub_class.open do |bkt|
17
+ expect(bkt).not_to be_closed
18
+ bucket = bkt
19
+ end
20
+ expect(bucket).to be_instance_of(sub_class)
21
+ expect(bucket).to be_closed
22
+ end
23
+ end
@@ -17,7 +17,14 @@ RSpec.describe BFS::Bucket::FS do
17
17
  expect(bucket.ls.to_a).to eq(['test.txt'])
18
18
  end
19
19
 
20
- it 'should support custom perms' do
20
+ it 'should support custom perms on #initialize' do
21
+ blob = BFS::Blob.new("file://#{tmpdir}/test.txt?perm=0666")
22
+ blob.create {|w| w.write 'foo' }
23
+ expect(blob.info.mode).to eq(0o666)
24
+ blob.close
25
+ end
26
+
27
+ it 'should support custom perms on #create' do
21
28
  blob = BFS::Blob.new("file://#{tmpdir}/test.txt")
22
29
  blob.create(perm: 0o666) {|w| w.write 'foo' }
23
30
  expect(blob.info.mode).to eq(0o666)
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe BFS do
4
+ it 'should resolve' do
5
+ bucket = BFS.resolve("file://#{Dir.tmpdir}")
6
+ expect(bucket).to be_instance_of(BFS::Bucket::FS)
7
+ bucket.close
8
+ end
9
+
10
+ it 'should resolve with block' do
11
+ BFS.resolve("file://#{Dir.tmpdir}") do |bucket|
12
+ expect(bucket).to be_instance_of(BFS::Bucket::FS)
13
+ expect(bucket).to receive(:close)
14
+ end
15
+ end
16
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bfs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitrij Denissenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-12 00:00:00.000000000 Z
11
+ date: 2020-07-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Minimalist abstraction for bucket storage
14
14
  email: dimitrij@blacksquaremedia.com
@@ -24,11 +24,14 @@ files:
24
24
  - lib/bfs/bucket/fs.rb
25
25
  - lib/bfs/bucket/in_mem.rb
26
26
  - lib/bfs/errors.rb
27
+ - lib/bfs/fs.rb
27
28
  - lib/bfs/helpers.rb
28
29
  - spec/bfs/blob_spec.rb
30
+ - spec/bfs/bucket/abstract_spec.rb
29
31
  - spec/bfs/bucket/fs_spec.rb
30
32
  - spec/bfs/bucket/in_mem_spec.rb
31
33
  - spec/bfs/helpers_spec.rb
34
+ - spec/bfs_spec.rb
32
35
  homepage: https://github.com/bsm/bfs.rb
33
36
  licenses:
34
37
  - Apache-2.0
@@ -41,19 +44,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
41
44
  requirements:
42
45
  - - ">="
43
46
  - !ruby/object:Gem::Version
44
- version: 2.5.0
47
+ version: 2.6.0
45
48
  required_rubygems_version: !ruby/object:Gem::Requirement
46
49
  requirements:
47
50
  - - ">="
48
51
  - !ruby/object:Gem::Version
49
52
  version: '0'
50
53
  requirements: []
51
- rubygems_version: 3.0.6
54
+ rubygems_version: 3.1.4
52
55
  signing_key:
53
56
  specification_version: 4
54
57
  summary: Multi-platform cloud bucket adapter
55
58
  test_files:
56
59
  - spec/bfs/blob_spec.rb
60
+ - spec/bfs/bucket/abstract_spec.rb
57
61
  - spec/bfs/bucket/fs_spec.rb
58
62
  - spec/bfs/bucket/in_mem_spec.rb
59
63
  - spec/bfs/helpers_spec.rb
64
+ - spec/bfs_spec.rb