bfs 0.6.4 → 0.7.3

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: d726d92a3fceb9313a497b3de260dde2d7ac4a26bbf7bbdcbdcd8b4b9f85225b
4
- data.tar.gz: de306b8f11a3b5de6f5bfef0a5e18325c30cd92bccb9aae05c09299ffae7275b
3
+ metadata.gz: 6195cd2787fbdb31ce0b8af2eb251effe1b7e3389f9932c5d33162b608b76d03
4
+ data.tar.gz: 22e24de8c867056c68beb0d49672400915dd4247660430e0a21bdf5b132dbdbe
5
5
  SHA512:
6
- metadata.gz: 5e09611641b682056651a500e17a6913004c45f0f852264cad2fa4133910d51241039370824b171c2eb49f5fee0ad60f7ea8ad9982b40539a0542f965a94d191
7
- data.tar.gz: 793230a864db0e7ed4c6e01b2dad75c5a71c2fc0dbaf593003d0050f3b4b39e7d7eb679483b55cb4f107a5898e9cac7be17f1c291aa95d6e5287dad132efa69c
6
+ metadata.gz: 17810380ac6d3452247c63057bc06e11c5d0e831afff661638c09be8f9ea0c3ec586b39d563b46a059d979c66a1752699f2633a01d2ea8ae47357c8fbd7d2f2a
7
+ data.tar.gz: 9843329935c5561d2df1ac6e957168a68ce2d76033541e34288e7b6f7da898a1ca64da63508d3d79cfc9922d899958a86423056557c9159fde086cb003be5fd4
@@ -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
@@ -40,7 +40,7 @@ module BFS
40
40
  end
41
41
  end
42
42
 
43
- def self.resolve(url)
43
+ def self.resolve(url, &block)
44
44
  url = url.is_a?(::URI) ? url.dup : URI.parse(url)
45
45
  rsl = @registry[url.scheme]
46
46
  raise ArgumentError, "Unable to resolve #{url}, scheme #{url.scheme} is not registered" unless rsl
@@ -49,7 +49,7 @@ module BFS
49
49
  CGI.parse(url.query.to_s).each do |key, values|
50
50
  opts[key.to_sym] = values.first
51
51
  end
52
- rsl.call(url, opts)
52
+ rsl.call(url, opts, block)
53
53
  end
54
54
 
55
55
  def self.norm_path(path)
@@ -64,6 +64,11 @@ module BFS
64
64
  mode = mode.to_i(8) if mode.is_a?(String)
65
65
  mode & 0o000777
66
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
67
72
  end
68
73
 
69
74
  require 'bfs/helpers'
@@ -3,12 +3,27 @@ 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
+ return blob unless block_given?
11
+
12
+ begin
13
+ yield blob
14
+ ensure
15
+ blob.close
16
+ end
17
+ end
18
+
6
19
  def initialize(url)
7
20
  url = url.is_a?(::URI) ? url.dup : URI.parse(url)
8
21
  @path = BFS.norm_path(url.path)
9
22
 
10
23
  url.path = '/'
11
24
  @bucket = BFS.resolve(url)
25
+
26
+ BFS.defer(self, :close)
12
27
  end
13
28
 
14
29
  # Info returns the blob info.
@@ -34,7 +49,7 @@ module BFS
34
49
 
35
50
  # Shortcut method to read the contents of the blob.
36
51
  def read(**opts)
37
- open(**opts, &:read)
52
+ self.open(**opts, &:read)
38
53
  end
39
54
 
40
55
  # Shortcut method to write data to blob.
@@ -5,13 +5,34 @@ module BFS
5
5
  class Abstract
6
6
  attr_reader :encoding, :perm
7
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
+ return bucket unless block_given?
13
+
14
+ begin
15
+ yield bucket
16
+ ensure
17
+ bucket.close
18
+ end
19
+ end
20
+
8
21
  # Initializes a new bucket
9
22
  # @param [Hash] opts options
10
23
  # @option opts [String] :encoding Custom encoding. Default: Encoding.default_external.
11
24
  # @option opts [Integer] :perm optional file permissions. Default: 0600.
12
- def initialize(encoding: Encoding.default_external, **_opts)
25
+ def initialize(encoding: Encoding.default_external, perm: nil, **_opts)
13
26
  @encoding = encoding
14
- @perm = perm
27
+
28
+ case perm
29
+ when Integer
30
+ @perm = perm
31
+ when String
32
+ @perm = perm.to_i(8)
33
+ end
34
+
35
+ BFS.defer(self, :close)
15
36
  end
16
37
 
17
38
  # Lists the contents of a bucket using a glob pattern
@@ -45,7 +66,7 @@ module BFS
45
66
  # @param [String] path The path to read from.
46
67
  # @param [Hash] opts Additional options, see #open.
47
68
  def read(path, **opts)
48
- open(path, **opts, &:read)
69
+ self.open(path, **opts, &:read)
49
70
  end
50
71
 
51
72
  # Shortcut method to write data to path
@@ -62,7 +83,7 @@ module BFS
62
83
  # @param [String] src The source path.
63
84
  # @param [String] dst The destination path.
64
85
  def cp(src, dst, **opts)
65
- open(src, **opts) do |r|
86
+ self.open(src, **opts) do |r|
66
87
  create(dst, **opts) do |w|
67
88
  IO.copy_stream(r, w)
68
89
  end
@@ -102,7 +102,7 @@ module BFS
102
102
  end
103
103
  end
104
104
 
105
- BFS.register('file') do |url, opts|
105
+ BFS.register('file') do |url, opts, block|
106
106
  parts = [url.host, url.path].compact
107
- BFS::Bucket::FS.new File.join(*parts), **opts
107
+ BFS::Bucket::FS.open(File.join(*parts), **opts, &block)
108
108
  end
@@ -0,0 +1 @@
1
+ require 'bfs/bucket/fs'
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe BFS::Blob do
3
+ RSpec.describe BFS::Blob, core: true do
4
4
  describe 'default' do
5
5
  let(:bucket) { BFS::Bucket::InMem.new }
6
6
  before { allow(BFS).to receive(:resolve).and_return(bucket) }
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe BFS::Bucket::Abstract, core: true 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
+ result = sub_class.open do |bkt|
17
+ expect(bkt).not_to be_closed
18
+ bucket = bkt
19
+ 21
20
+ end
21
+ expect(result).to eq(21)
22
+ expect(bucket).to be_instance_of(sub_class)
23
+ expect(bucket).to be_closed
24
+ end
25
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe BFS::Bucket::FS do
3
+ RSpec.describe BFS::Bucket::FS, core: true do
4
4
  let(:tmpdir) { Dir.mktmpdir }
5
5
  after { FileUtils.rm_rf tmpdir }
6
6
  subject { described_class.new(tmpdir) }
@@ -15,9 +15,17 @@ RSpec.describe BFS::Bucket::FS do
15
15
  bucket = BFS.resolve("file://#{tmpdir}")
16
16
  expect(bucket).to be_instance_of(described_class)
17
17
  expect(bucket.ls.to_a).to eq(['test.txt'])
18
+ bucket.close
18
19
  end
19
20
 
20
- it 'should support custom perms' do
21
+ it 'should support custom perms on #initialize' do
22
+ blob = BFS::Blob.new("file://#{tmpdir}/test.txt?perm=0666")
23
+ blob.create {|w| w.write 'foo' }
24
+ expect(blob.info.mode).to eq(0o666)
25
+ blob.close
26
+ end
27
+
28
+ it 'should support custom perms on #create' do
21
29
  blob = BFS::Blob.new("file://#{tmpdir}/test.txt")
22
30
  blob.create(perm: 0o666) {|w| w.write 'foo' }
23
31
  expect(blob.info.mode).to eq(0o666)
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe BFS::Bucket::InMem do
3
+ RSpec.describe BFS::Bucket::InMem, core: true do
4
4
  it_behaves_like 'a bucket'
5
5
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe BFS::TempWriter do
3
+ RSpec.describe BFS::TempWriter, core: true do
4
4
  let(:closer) { proc {} }
5
5
  subject { described_class.new 'test', &closer }
6
6
 
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe BFS, core: true 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.4
4
+ version: 0.7.3
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-17 00:00:00.000000000 Z
11
+ date: 2020-07-10 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.1.2
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