bfs 0.7.1 → 0.7.6

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