bfs 0.7.2 → 0.8.0

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: 20aaadf82c4feef66bb9f7ca3a50c2da292e5b107d69d5e055e139cea1aca352
4
- data.tar.gz: aef5f242aa8e8b22cb940ac20b280650ba4d499025a5cc3efa620b8c6f375d7e
3
+ metadata.gz: 3de22f9cab6ba21d594854a2fcec49cc215b7c10c6f6b5b9cb1528ba6ce96b59
4
+ data.tar.gz: cc3b427ff41229556b7b39a9d0ad5d61afdd0439fa984aafadd0aa9635ac4664
5
5
  SHA512:
6
- metadata.gz: 77722ad5d90e91f1abbaac4dfb633ad355de949c6a9e23cf383690de426666344e4431fa3a2da0490f7b065744e0786709beb8f18e1cd8ad2ade12ede3e895c7
7
- data.tar.gz: dc0fe99895a120ebcf6e4d6f5cb2f62fc01d2caa62ac2a985a336e9f77bc186f0edeb3ae17899bec22753c61ba63dc09b8c8c61f209808c02202e6aa141d32c8
6
+ metadata.gz: 569ac3d4e157eebf08f948eab831f214a900d29a96028a703d541d3fa7de7fdcde6a2cb11413ff802c459ff163cff15feb00c3477abcae7b18d77c302255d529
7
+ data.tar.gz: 2804530bcc9aaf60f1b475a6948b357242dc96e15788835e34d6cc1989ec7bda8e0bd66372427ce4aa9d5b923eda5468a9c33087b716ac3ca379f391a6192f43
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]
@@ -32,6 +32,9 @@ module BFS
32
32
  end
33
33
 
34
34
  # Creates the blob and opens it for writing.
35
+ # If a block is passed the writer is automatically committed in the end.
36
+ # If no block is passed, you must manually call #commit to persist the
37
+ # result.
35
38
  def create(**opts, &block)
36
39
  @bucket.create(path, **opts, &block)
37
40
  end
@@ -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::Writer.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
@@ -1,5 +1,6 @@
1
1
  require 'bfs'
2
2
  require 'stringio'
3
+ require 'delegate'
3
4
 
4
5
  module BFS
5
6
  module Bucket
@@ -7,6 +8,21 @@ module BFS
7
8
  class InMem < Abstract
8
9
  Entry = Struct.new(:io, :mtime, :content_type, :metadata)
9
10
 
11
+ class Writer < DelegateClass(::StringIO)
12
+ include BFS::Writer::Mixin
13
+
14
+ def initialize(encoding:, &on_commit)
15
+ @on_commit = on_commit
16
+
17
+ sio = StringIO.new
18
+ sio.set_encoding(encoding)
19
+ super sio
20
+ end
21
+
22
+ alias close! close
23
+ alias commit_ref __getobj__
24
+ end
25
+
10
26
  def initialize(**opts)
11
27
  super(**opts.dup)
12
28
  @files = {}
@@ -43,18 +59,9 @@ module BFS
43
59
  # @option opts [String] :content_type Custom content type.
44
60
  # @option opts [Hash] :metadata Metadata key-value pairs.
45
61
  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
62
+ Writer.new(encoding: encoding) do |wio|
63
+ @files[norm_path(path)] = Entry.new(wio, Time.now, content_type, norm_meta(metadata))
64
+ end.perform(&block)
58
65
  end
59
66
 
60
67
  # Opens an existing file for reading
@@ -2,21 +2,45 @@ require 'tempfile'
2
2
  require 'delegate'
3
3
 
4
4
  module BFS
5
- class TempWriter < DelegateClass(::Tempfile)
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
5
+ class Writer < DelegateClass(::Tempfile)
6
+ module Mixin
7
+ def perform
8
+ return self unless block_given?
9
+
10
+ begin
11
+ yield self
12
+ commit
13
+ ensure
14
+ discard
15
+ end
16
+ end
17
+
18
+ def commit
19
+ close
20
+ return false if @on_commit.nil?
21
+
22
+ @on_commit.call(commit_ref)
23
+ true
24
+ ensure
25
+ discard
26
+ end
27
+
28
+ def discard
29
+ @on_commit = nil
30
+ close!
31
+ end
11
32
  end
12
33
 
13
- def close
14
- return if closed?
34
+ include Mixin
35
+
36
+ def initialize(name, tempdir: nil, perm: nil, **opts, &on_commit)
37
+ @on_commit = on_commit
15
38
 
16
- path = @tempfile.path
17
- @tempfile.close
18
- @closer&.call(path)
19
- @tempfile.unlink
39
+ tempfile = ::Tempfile.new(File.basename(name.to_s), tempdir, **opts)
40
+ tempfile.chmod(perm) if perm
41
+ super tempfile
20
42
  end
43
+
44
+ alias commit_ref path
21
45
  end
22
46
  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
@@ -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,22 +1,28 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe BFS::TempWriter do
4
- let(:closer) { proc {} }
5
- subject { described_class.new 'test', &closer }
6
-
7
- it 'should behave like a File' do
8
- missing = ::File.public_instance_methods - subject.public_methods
9
- expect(missing).to be_empty
10
- end
3
+ RSpec.describe BFS::Writer, core: true do
4
+ let(:on_commit) { proc { true } }
5
+ subject { described_class.new 'test', &on_commit }
11
6
 
12
7
  it 'should support custom params' do
13
- subject = described_class.new 'test', perm: 0o640, &closer
8
+ subject = described_class.new 'test', perm: 0o640, &on_commit
14
9
  expect(subject.stat.mode).to eq(0o100640)
15
- expect(subject.close).to be_truthy
10
+ expect(subject.commit).to be(true)
11
+ end
12
+
13
+ it 'should execute a on_commit block' do
14
+ expect(on_commit).to receive(:call).with(subject.path).once
15
+ expect(subject.commit).to be(true)
16
+ expect(subject.commit).to be(false)
17
+ end
18
+
19
+ it 'may skip on_commit block' do
20
+ expect(on_commit).not_to receive(:call)
21
+ expect(subject.discard).to be(true)
16
22
  end
17
23
 
18
- it 'should exectute a closer block' do
19
- expect(closer).to receive(:call).with(subject.path)
20
- expect(subject.close).to be_truthy
24
+ it 'should not auto-commit on close' do
25
+ expect(on_commit).not_to receive(:call)
26
+ expect(subject.close).to be_nil
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.2
4
+ version: 0.8.0
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-12-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Minimalist abstraction for bucket storage
14
14
  email: dimitrij@blacksquaremedia.com