bfs 0.7.1 → 0.7.6

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: 4851ad3e633d9ba6e2e1533206f9810390ff29959d047916f32004c4432bc282
4
- data.tar.gz: 9129b8d9d6a87a8a5e97bd45145b4936f07bfd27c6c088bad6797477afcbf795
3
+ metadata.gz: cd67ecfdb038d1809be4193caf014dfd9e8bcba4e26a4cd04da3c64e61522ddc
4
+ data.tar.gz: 17586a9b02836e8bdcbf4da6bc822d9c169cca9823b5817357dba1d4a5f1a072
5
5
  SHA512:
6
- metadata.gz: 015a5be095930a9f2a4b446809ac4d2684cd4c49ff3b56fc7a28b1f43b2bfe49953625092fcdced43969407d9d40e63eabc6f127fcb58d139d7de55b4b6f98d3
7
- data.tar.gz: 8a3dcc158679457ba9881a29d47c0e4a1c316b040c2080bba61f80c596f20245125b1071a47c9540f65a588e94cccdf519bf0d975a38693c6b5e89ccee5c9326
6
+ metadata.gz: e1ab4426da76e5a0de997d9b1f355c549197e4bd199629a37f6f787a9dcd068020c04ed190f117461490bb75d86a4070b475d481cc679005de731dacabb8fd64
7
+ data.tar.gz: 355cd6811da84829fad5f59927535b681c3f357968681d175c8a400f4e0b445920120daba944ea679dc965b582d65781063e2be199ffc372cda4e7df6739f89c
data/lib/bfs.rb CHANGED
@@ -4,6 +4,8 @@ require 'cgi'
4
4
  module BFS
5
5
  class FileInfo < Hash
6
6
  def initialize(**attrs)
7
+ super(nil)
8
+
7
9
  update(size: 0, mtime: Time.at(0), mode: 0, metadata: {})
8
10
  update(attrs)
9
11
  end
@@ -36,10 +38,23 @@ module BFS
36
38
  def self.register(*schemes, &resolver)
37
39
  @registry ||= {}
38
40
  schemes.each do |scheme|
41
+ scheme = scheme.to_s
42
+ raise(ArgumentError, "scheme #{scheme} is already registered") if @registry.key?(scheme)
43
+
39
44
  @registry[scheme] = resolver
40
45
  end
41
46
  end
42
47
 
48
+ def self.unregister(*schemes)
49
+ @registry ||= {}
50
+ schemes.each do |scheme|
51
+ scheme = scheme.to_s
52
+ raise(ArgumentError, "scheme #{scheme} is not registered") unless @registry.key?(scheme)
53
+
54
+ @registry.delete(scheme)
55
+ end
56
+ end
57
+
43
58
  def self.resolve(url, &block)
44
59
  url = url.is_a?(::URI) ? url.dup : URI.parse(url)
45
60
  rsl = @registry[url.scheme]
@@ -7,12 +7,13 @@ module BFS
7
7
  # If a block is given, blobs are automatically closed after the block is yielded.
8
8
  def self.open(url)
9
9
  blob = new(url)
10
+ return blob unless block_given?
11
+
10
12
  begin
11
13
  yield blob
12
14
  ensure
13
15
  blob.close
14
- end if block_given?
15
- blob
16
+ end
16
17
  end
17
18
 
18
19
  def initialize(url)
@@ -9,12 +9,13 @@ module BFS
9
9
  # If a block is given, buckets are automatically closed after the block is yielded.
10
10
  def self.open(*args, **opts)
11
11
  bucket = new(*args, **opts)
12
+ return bucket unless block_given?
13
+
12
14
  begin
13
15
  yield bucket
14
16
  ensure
15
17
  bucket.close
16
- end if block_given?
17
- bucket
18
+ end
18
19
  end
19
20
 
20
21
  # Initializes a new bucket
@@ -42,14 +42,9 @@ module BFS
42
42
  full = @root.join(norm_path(path))
43
43
  FileUtils.mkdir_p(full.dirname.to_s)
44
44
 
45
- temp = BFS::TempWriter.new(full, encoding: encoding, perm: perm) {|t| FileUtils.mv t, full.to_s }
46
- return temp unless block
47
-
48
- begin
49
- yield temp
50
- ensure
51
- temp.close
52
- end
45
+ BFS::TempWriter.new(full, encoding: encoding, perm: perm) do |temp|
46
+ FileUtils.mv temp, full.to_s
47
+ end.perform(&block)
53
48
  end
54
49
 
55
50
  # Opens an existing file for reading
@@ -7,6 +7,37 @@ module BFS
7
7
  class InMem < Abstract
8
8
  Entry = Struct.new(:io, :mtime, :content_type, :metadata)
9
9
 
10
+ class Writer < DelegateClass(::StringIO)
11
+ def initialize(encoding:, &closer)
12
+ @closer = closer
13
+
14
+ sio = StringIO.new
15
+ sio.set_encoding(encoding)
16
+ super sio
17
+ end
18
+
19
+ def close
20
+ super.tap do
21
+ @closer&.call(self)
22
+ end
23
+ end
24
+
25
+ def close!
26
+ __getobj__.close
27
+ end
28
+
29
+ def perform
30
+ return self unless block_given?
31
+
32
+ begin
33
+ yield self
34
+ close
35
+ ensure
36
+ close!
37
+ end
38
+ end
39
+ end
40
+
10
41
  def initialize(**opts)
11
42
  super(**opts.dup)
12
43
  @files = {}
@@ -43,18 +74,9 @@ module BFS
43
74
  # @option opts [String] :content_type Custom content type.
44
75
  # @option opts [Hash] :metadata Metadata key-value pairs.
45
76
  def create(path, encoding: self.encoding, content_type: nil, metadata: nil, **_opts, &block)
46
- io = StringIO.new
47
- io.set_encoding(encoding)
48
-
49
- entry = Entry.new(io, Time.now, content_type, norm_meta(metadata))
50
- @files[norm_path(path)] = entry
51
- return io unless block
52
-
53
- begin
54
- yield(io)
55
- ensure
56
- io.close
57
- end
77
+ Writer.new(encoding: encoding) do |wio|
78
+ @files[norm_path(path)] = Entry.new(wio, Time.now, content_type, norm_meta(metadata))
79
+ end.perform(&block)
58
80
  end
59
81
 
60
82
  # Opens an existing file for reading
@@ -4,19 +4,31 @@ require 'delegate'
4
4
  module BFS
5
5
  class TempWriter < DelegateClass(::Tempfile)
6
6
  def initialize(name, tempdir: nil, perm: nil, **opts, &closer)
7
- @closer = closer
8
- @tempfile = ::Tempfile.new(File.basename(name.to_s), tempdir, **opts)
9
- @tempfile.chmod(perm) if perm
10
- super @tempfile
7
+ @closer = closer
8
+
9
+ tempfile = ::Tempfile.new(File.basename(name.to_s), tempdir, **opts)
10
+ tempfile.chmod(perm) if perm
11
+ super tempfile
12
+ end
13
+
14
+ def perform
15
+ return self unless block_given?
16
+
17
+ begin
18
+ yield self
19
+ close
20
+ ensure
21
+ close!
22
+ end
11
23
  end
12
24
 
13
25
  def close
14
26
  return if closed?
15
27
 
16
- path = @tempfile.path
17
- @tempfile.close
18
- @closer&.call(path)
19
- @tempfile.unlink
28
+ super.tap do
29
+ @closer&.call(path)
30
+ end
31
+ unlink
20
32
  end
21
33
  end
22
34
  end
@@ -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) }
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe BFS::Bucket::Abstract do
3
+ RSpec.describe BFS::Bucket::Abstract, core: true do
4
4
  it 'should open with a block' do
5
5
  sub_class = Class.new(described_class) do
6
6
  def close
@@ -13,10 +13,12 @@ RSpec.describe BFS::Bucket::Abstract do
13
13
  end
14
14
 
15
15
  bucket = nil
16
- sub_class.open do |bkt|
16
+ result = sub_class.open do |bkt|
17
17
  expect(bkt).not_to be_closed
18
18
  bucket = bkt
19
+ 21
19
20
  end
21
+ expect(result).to eq(21)
20
22
  expect(bucket).to be_instance_of(sub_class)
21
23
  expect(bucket).to be_closed
22
24
  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,6 +15,7 @@ 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
21
  it 'should support custom perms on #initialize' do
@@ -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
 
@@ -15,8 +15,14 @@ RSpec.describe BFS::TempWriter do
15
15
  expect(subject.close).to be_truthy
16
16
  end
17
17
 
18
- it 'should exectute a closer block' do
19
- expect(closer).to receive(:call).with(subject.path)
18
+ it 'should execute a closer block' do
19
+ expect(closer).to receive(:call).with(subject.path).once
20
20
  expect(subject.close).to be_truthy
21
+ expect(subject.close).to be_nil
22
+ end
23
+
24
+ it 'may skip closer block' do
25
+ expect(closer).not_to receive(:call)
26
+ expect(subject.close!).to be_truthy
21
27
  end
22
28
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe BFS do
3
+ RSpec.describe BFS, core: true do
4
4
  it 'should resolve' do
5
5
  bucket = BFS.resolve("file://#{Dir.tmpdir}")
6
6
  expect(bucket).to be_instance_of(BFS::Bucket::FS)
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.7.1
4
+ version: 0.7.6
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-07-02 00:00:00.000000000 Z
11
+ date: 2020-11-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Minimalist abstraction for bucket storage
14
14
  email: dimitrij@blacksquaremedia.com
@@ -51,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
51
51
  - !ruby/object:Gem::Version
52
52
  version: '0'
53
53
  requirements: []
54
- rubygems_version: 3.1.4
54
+ rubygems_version: 3.1.2
55
55
  signing_key:
56
56
  specification_version: 4
57
57
  summary: Multi-platform cloud bucket adapter