bfs 0.6.4 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
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