defog 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -15,6 +15,10 @@ it also works with the local file system as a "provider" so that you can,
15
15
  e.g. use the local file system for development and the cloud for
16
16
  production.
17
17
 
18
+ Defog also provides a few simple remote-file management methods to minimize
19
+ the need to dig down into the Fog layer; but full access to the underlying
20
+ fog objects is available should it be needed.
21
+
18
22
  == Usage Summary
19
23
 
20
24
  Full Rdoc is available at http://rubydoc.info/gems/defog
@@ -35,7 +39,7 @@ object, which proxies files in a specific remote location, e.g.:
35
39
 
36
40
  === Proxy a file
37
41
 
38
- Proxy a remote file by creating a <code>Defog::File</code> object:
42
+ Open a proxy to a remote file by creating a <code>Defog::File</code> object:
39
43
 
40
44
  file = defog.file("key/of/file", mode)
41
45
  # ... access file ...
@@ -46,7 +50,14 @@ Proxy a remote file by creating a <code>Defog::File</code> object:
46
50
  end
47
51
 
48
52
  <code>mode</code> can be "r", "r+", "w", "w+", "a", or "a+" with the usual
49
- semantics. Closing the file object (explicitly or implicitly at the end of
53
+ semantics.
54
+
55
+ When opened in a readable mode ("r", "r+", "w+", "a+"), first caches the
56
+ cloud file in the local proxy. When opened in a writeable mode ("r+", "w",
57
+ "w+", "a", "a+"), arranges to upload the changes back to the cloud file
58
+ at close time.
59
+
60
+ Closing the file object (explicitly or implicitly at the end of
50
61
  the block) synchronizes the local proxy with the remote storage and (by
51
62
  default) deletes the local proxy file.
52
63
 
@@ -65,11 +76,24 @@ You can also access the proxy file via its path, allowing things such as
65
76
 
66
77
  (Note that the proxy file path has the same file extension as the cloud key string.)
67
78
 
68
-
69
79
  To suppress updating the remote storage, delete the local proxy file before
70
80
  closing (e.g. via <code>File.unlink(file.path)</code>) or pass
71
81
  <code>:synchronize => false</code> to the <code>#close</code> method.
72
82
 
83
+ === Proxy handle
84
+
85
+ Calling Defog::Proxy#file without a mode returns a Defog::Handle object that supports remote file query and manipulation:
86
+
87
+ proxy.file("key").exist? # => returns true if the remove file exists
88
+ proxy.file("key").delete # => deletes the remote file
89
+
90
+ In fact, <code>proxy.file("key", mode, options, &block)</code> is really just shorthand for
91
+
92
+ proxy.file("key").open(mode, options, &block)
93
+
94
+ In addition, the handle allows you to look up the path where the local proxy file will be if/when you open the proxy (but without actually doing the proxying).
95
+
96
+ proxy.file("key").proxy_path # returns pathname where proxy file will be when you open
73
97
 
74
98
  === Persistence
75
99
 
@@ -83,7 +107,7 @@ via
83
107
 
84
108
  or
85
109
 
86
- file.close(:persist => true) # overrides setting at runtime
110
+ file.close(:persist => true)
87
111
 
88
112
  When opening a file whose local proxy has been persisted, Defog checks to see if
89
113
  the local proxy is out of date and if so replaces it.
@@ -100,9 +124,9 @@ Local proxy files are stored by default in
100
124
  #{tmproot}/defog/#{provider}/#{location}/#{key}
101
125
 
102
126
  where <code>tmproot</code> is <code>Rails.root+"tmp"</code> if Rails is
103
- defined, otherwise <code>Dir.tmpdir()</code>. For AWS,
104
- <code>location</code> is the bucket name, and for Local it's the
105
- local_root directory path with slashes replaced with dashes
127
+ defined, otherwise <code>Dir.tmpdir()</code>. For :AWS,
128
+ <code>location</code> is the bucket name, and for :local it's the
129
+ <code>local_root</code> directory path with slashes replaced with underscores.
106
130
 
107
131
  See the documentation for configuring other locations.
108
132
 
@@ -113,10 +137,8 @@ Gemfile:
113
137
 
114
138
  == Compatibility
115
139
 
116
- Defog has (so far) been tested using MRI 1.9.3 and
117
- [fog](https://rubygems.org/gems/fog) storage providers :Local and :AWS
118
-
119
- == History
140
+ Defog has (so far) been tested on MRI 1.9.3 using
141
+ [fog](https://rubygems.org/gems/fog) storage providers :local and :AWS
120
142
 
121
143
  == Copyright
122
144
 
data/lib/defog.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'defog/error'
2
2
  require 'defog/file'
3
3
  require 'defog/fog_wrapper'
4
+ require 'defog/handle'
4
5
  require 'defog/proxy'
5
6
  require 'defog/version'
data/lib/defog/file.rb CHANGED
@@ -32,18 +32,21 @@ module Defog
32
32
  # the proxy deleted. See File#close for more details.
33
33
  class File < ::File
34
34
  def self.get(opts={}, &block) #:nodoc:
35
- opts = opts.keyword_args(:proxy => :required, :key => :required, :mode => :required, :persist => :optional)
35
+ opts = opts.keyword_args(:handle => :required, :mode => :required, :persist => :optional)
36
+
37
+ handle = opts.handle
38
+ key = handle.key
39
+ proxy_path = handle.proxy_path
36
40
 
37
- proxy_path = opts[:proxy_path] = Pathname.new("#{opts.proxy.proxy_root}/#{opts.key}").expand_path
38
41
  proxy_path.dirname.mkpath
39
42
 
40
43
  case opts.mode
41
44
  when "r" then
42
- opts.proxy.fog_wrapper.get_file(opts.key, proxy_path)
45
+ handle.proxy.fog_wrapper.get_file(key, proxy_path)
43
46
  when "w", "w+" then
44
47
  opts[:upload] = true
45
48
  when "r+", "a", "a+" then
46
- opts.proxy.fog_wrapper.get_file(opts.key, proxy_path)
49
+ handle.proxy.fog_wrapper.get_file(key, proxy_path)
47
50
  opts[:upload] = true
48
51
  else
49
52
  raise ArgumentError, "Invalid mode #{opts.mode.inspect}"
@@ -53,12 +56,12 @@ module Defog
53
56
  end
54
57
 
55
58
  def initialize(opts={}, &block) #:nodoc:
56
- @defog = opts.keyword_args(:proxy => :required, :mode => :required, :key => :required, :proxy_path => :required, :upload => :optional, :persist => :optional)
57
- super(@defog.proxy_path, @defog.mode, &block)
59
+ @defog = opts.keyword_args(:handle => :required, :mode => :required, :upload => :optional, :persist => :optional)
60
+ super(@defog.handle.proxy_path, @defog.mode, &block)
58
61
  end
59
62
 
60
- # Closes the proxy file and, in the common case, synchronizes the cloud storage
61
- # then deletes the proxy file.
63
+ # Closes the proxy file and synchronizes the cloud storage (if it was
64
+ # opened as writeable) then deletes the proxy file.
62
65
  #
63
66
  # Synchronization can be suppressed by passing the option
64
67
  # :synchronize => false
@@ -74,9 +77,10 @@ module Defog
74
77
  def close(opts={})
75
78
  opts = opts.keyword_args(:persist => @defog.persist, :synchronize => true)
76
79
  super()
77
- if @defog.proxy_path.exist?
78
- @defog.proxy.fog_wrapper.put_file(@defog.key, @defog.proxy_path) if @defog.upload and opts.synchronize
79
- @defog.proxy_path.unlink unless opts.persist
80
+ handle = @defog.handle
81
+ if handle.proxy_path.exist?
82
+ handle.proxy.fog_wrapper.put_file(handle.key, handle.proxy_path) if @defog.upload and opts.synchronize
83
+ handle.proxy_path.unlink unless opts.persist
80
84
  end
81
85
  end
82
86
  end
@@ -6,6 +6,7 @@ module Defog #:nodoc: all
6
6
  class FogWrapper #:nodoc: all
7
7
 
8
8
  attr_reader :location
9
+ attr_reader :fog_connection
9
10
  attr_reader :fog_directory
10
11
 
11
12
  def self.connect(opts={})
@@ -40,9 +41,9 @@ module Defog #:nodoc: all
40
41
 
41
42
  def initialize(opts={})
42
43
  opts = opts.keyword_args(:local_root => :required)
43
- directory = Pathname.new(opts.local_root).realpath
44
- @location = directory.to_s.gsub(%r{/},'_')
45
- @fog_connection = Fog::Storage.new(:provider => provider, :local_root => directory)
44
+ @local_root = Pathname.new(opts.local_root).realpath
45
+ @location = @local_root.to_s.gsub(%r{/},'_')
46
+ @fog_connection = Fog::Storage.new(:provider => provider, :local_root => @local_root)
46
47
  @fog_directory = @fog_connection.directories.get('.')
47
48
  end
48
49
 
@@ -50,6 +51,15 @@ module Defog #:nodoc: all
50
51
  Digest::MD5.hexdigest(fog_head(key).body)
51
52
  end
52
53
 
54
+ def url(key, expiry)
55
+ localpath = Pathname.new("#{@local_root}/#{key}").expand_path
56
+ if defined?(Rails)
57
+ relative = localpath.relative_path_from Rails.root + "public" rescue nil
58
+ return "/" + relative.to_s if relative and not relative.to_s.start_with? "../"
59
+ end
60
+ "file://#{localpath}"
61
+ end
62
+
53
63
  end
54
64
 
55
65
  class Aws < FogWrapper
@@ -67,6 +77,10 @@ module Defog #:nodoc: all
67
77
  fog_head(key).content_md5
68
78
  end
69
79
 
80
+ def url(key, expiry)
81
+ fog_head(key).url(expiry)
82
+ end
83
+
70
84
  end
71
85
  end
72
86
  end
@@ -0,0 +1,84 @@
1
+ module Defog
2
+ # Create a Defog::Handle proxy instance via Defog::Proxy#file, such as
3
+ #
4
+ # defog = Defog::Proxy.new(:provider => :AWS, :aws_access_key_id => access_key, ...)
5
+ #
6
+ # handle = defog.file("key/to/my/file")
7
+ #
8
+ # or
9
+ #
10
+ # defog.file("key/to/my/file") do |handle|
11
+ # # ... access the proxy handle ...
12
+ # end
13
+ #
14
+ # The #proxy_path attribute method returns a <code>Pathname</code>
15
+ # giving the local proxy file location. Querying the attribute does
16
+ # <i>not</i> upload, download, synchronize, or otherwise interact with
17
+ # the cloud or local proxy file in any way -- just returns a constructed
18
+ # a Pathname.
19
+ #
20
+ class Handle
21
+
22
+ attr_reader :key
23
+ attr_reader :proxy #:nodoc:
24
+ attr_reader :proxy_path
25
+
26
+ def initialize(proxy, key) #:nodoc:
27
+ @proxy = proxy
28
+ @key = key
29
+ @proxy_path = Pathname.new("#{@proxy.proxy_root}/#{@key}").expand_path
30
+ end
31
+
32
+ # Returns true if the remote cloud file exists
33
+ def exist?
34
+ !!@proxy.fog_wrapper.fog_head(@key)
35
+ end
36
+
37
+ # Deletes the remote cloud file
38
+ def delete
39
+ @proxy.fog_wrapper.fog_head(@key).destroy
40
+ end
41
+
42
+ # Returns a URL to access the remote cloud file.
43
+ #
44
+ # The option
45
+ # :expiry => time
46
+ # Specifies the expiration of time-limited URLS when using :AWS. The default is
47
+ # <code>Time.now + 10.minutes</code>. The expiry is ignored when using :local
48
+ #
49
+ # For :local cloud files, if Rails is defined and the file is in the
50
+ # Rails app's public directory, returns a site path relative to
51
+ # the public directory. Otherwise returns a <code>"file://"</code> URL
52
+ def url(opts={})
53
+ opts = opts.keyword_args(:expiry => Time.now + 10*60)
54
+ @proxy.fog_wrapper.url(@key, opts.expiry)
55
+ end
56
+
57
+ # Returns the underlying Fog::Model, should you need it for something.
58
+ def fog_model
59
+ @proxy.fog_wrapper.fog_head(@key)
60
+ end
61
+
62
+ # Returns a Defog::File object, which is a specialization of ::File.
63
+ #
64
+ # <code>mode</code> can be "r", "r+", "w", "w+", "a", or "a+" with the
65
+ # usual semantics. When opened in a readable mode ("r", "r+", "w+",
66
+ # "a+"), first caches the cloud file in the local proxy. When opened
67
+ # in a writeable mode ("r+", "w", "w+", "a", "a+"), arranges to upload
68
+ # the changes back to the cloud file at close time.
69
+ #
70
+ # Like ::File.open, if called with a block yields the file object to
71
+ # the block and ensures the file will be closed when leaving the block.
72
+ #
73
+ # Normally upon close the proxy file is synchronized as needed and then deleted.
74
+ # Pass
75
+ # :persist => true
76
+ # to suppress deleting the file and so maintain the file after closing. See File#close for more
77
+ # details.
78
+ def open(mode, opts={}, &block)
79
+ opts = opts.keyword_args(:persist)
80
+ File.get(opts.merge(:handle => self, :mode => mode), &block)
81
+ end
82
+
83
+ end
84
+ end
data/lib/defog/proxy.rb CHANGED
@@ -59,26 +59,35 @@ module Defog
59
59
  @fog_wrapper.location
60
60
  end
61
61
 
62
- # Proxy a remote cloud file. Returns a Defog::File object, which is a
63
- # specialization of ::File.
64
- #
65
- # <code>key</code> is the cloud storage key for the file.
66
- #
67
- # <code>mode</code> can be "r", "r+", "w", "w+", "a", or "a+" with the
68
- # usual semantics.
62
+ # Returns the underlying Fog::Storage object for the cloud connection
63
+ def fog_connection
64
+ @fog_wrapper.fog_connection
65
+ end
66
+
67
+ # Returns the Fog directory object for the root of the cloud files
68
+ def fog_directory
69
+ @fog_wrapper.fog_directory
70
+ end
71
+
72
+ # Proxy a remote cloud file. Returns a Defog::Handle object that
73
+ # represents the file.
69
74
  #
70
- # Like ::File.open, if called with a block yields the file object to
71
- # the block and ensures the file will be closed when leaving the block.
75
+ # If a <code>mode</code> is specified given opens a proxy file via
76
+ # Defog::Handle#open (passing it the mode and other options and
77
+ # optional block), returning instead the Defog::File object.
72
78
  #
73
- # Normally the proxy file is synchronized and then deleted upon close.
74
- # Pass
75
- # :persist => true
76
- # to maintain the file after closing. See File#close for more
77
- # details.
79
+ # Thus
80
+ # proxy.file("key", mode, options, &block)
81
+ # is shorthand for
82
+ # proxy.file("key").open(mode, options, &block)
78
83
  #
79
- def file(key, mode, opts={}, &block)
80
- opts = opts.keyword_args(:persist)
81
- File.get(opts.merge(:proxy => self, :key => key, :mode => mode), &block)
84
+ def file(key, mode=nil, opts={}, &block)
85
+ handle = Handle.new(self, key)
86
+ case
87
+ when mode then handle.open(mode, opts, &block) if mode
88
+ when block then block.call(handle)
89
+ else handle
90
+ end
82
91
  end
83
92
 
84
93
  end
data/lib/defog/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Defog
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/file_spec.rb CHANGED
@@ -229,29 +229,6 @@ describe "Defog::Proxy::File" do
229
229
 
230
230
  end
231
231
 
232
- def key
233
- example.metadata[:full_description].gsub(/\+/,'plus').gsub(/\W/,'-') + "/filename"
234
- end
235
-
236
- def create_remote(body)
237
- @proxy.fog_wrapper.fog_directory.files.create(:key => key, :body => body)
238
- end
239
-
240
- def proxy_path
241
- Pathname.new("#{@proxy.proxy_root}/#{key}").expand_path
242
- end
243
-
244
- def create_proxy(body)
245
- path = proxy_path
246
- path.dirname.mkpath
247
- path.open("w") do |f|
248
- f.write(body)
249
- end
250
- end
251
-
252
- def remote_body
253
- @proxy.fog_wrapper.fog_directory.files.get(key).body
254
- end
255
232
 
256
233
 
257
234
  end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples "a handle" do |proxyargs|
4
+
5
+ before(:all) do
6
+ @proxy = Defog::Proxy.new(proxyargs)
7
+ end
8
+
9
+ before(:each) do
10
+ @handle = @proxy.file(key)
11
+ end
12
+
13
+ it "should report exist? true if remode cloud file exists" do
14
+ create_remote("i exist")
15
+ @handle.should be_exist
16
+ end
17
+
18
+ it "should report exist? false if remode cloud file does not exists" do
19
+ @handle.should_not be_exist
20
+ end
21
+
22
+ it "should delete a remote cloud file" do
23
+ create_remote("delete me")
24
+ remote_exist?.should be_true
25
+ @handle.delete
26
+ remote_exist?.should be_false
27
+ end
28
+
29
+ it "should return a URL to a file" do
30
+ create_remote("reach out to me")
31
+ @handle.url.should be_a String
32
+ end
33
+
34
+ it "should open a file" do
35
+ Defog::File.should_receive(:open).with(hash_including(:handle => @handle, :mode => "w"))
36
+ @handle.open("w")
37
+ end
38
+
39
+ it "should return a Fog model" do
40
+ create_remote("foggy")
41
+ @handle.fog_model.body.should == "foggy"
42
+ end
43
+
44
+
45
+ end
46
+
47
+ describe Defog::Handle do
48
+
49
+ context "Local" do
50
+ before(:all) do
51
+ Fog.unmock!
52
+ end
53
+
54
+ args = {:provider => :local, :local_root => LOCAL_CLOUD_PATH}
55
+
56
+ it_should_behave_like "a handle", args
57
+
58
+ it "should return a file:// URL" do
59
+ @proxy = Defog::Proxy.new(args)
60
+ @proxy.file(key).url.should == "file://" + (LOCAL_CLOUD_PATH + key).to_s
61
+ end
62
+
63
+ context "with a rails app" do
64
+
65
+ it "should return a path relative to public if in public" do
66
+ with_rails_defined do
67
+ @proxy = Defog::Proxy.new(:provider => :local, :local_root => (Rails.root + "public/defog").tap(&:mkpath))
68
+ @proxy.file(key).url.should == "/defog/#{key}"
69
+ end
70
+ end
71
+
72
+ it "should return a file:// path if not in public" do
73
+ with_rails_defined do
74
+ @proxy = Defog::Proxy.new(args)
75
+ @proxy.file(key).url.should == "file://" + (LOCAL_CLOUD_PATH + key).to_s
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ context "AWS" do
83
+ before(:all) do
84
+ Fog.mock!
85
+ end
86
+
87
+ args = {:provider => :AWS, :aws_access_key_id => "dummyid", :aws_secret_access_key => "dummysecret", :region => "eu-west-1", :bucket => "tester"}
88
+ it_should_behave_like "a handle", args
89
+
90
+ end
91
+
92
+ end
data/spec/proxy_spec.rb CHANGED
@@ -8,12 +8,9 @@ shared_examples "a proxy" do |args|
8
8
  end
9
9
 
10
10
  it "should default proxy root to Rails.root" do
11
- begin
12
- Kernel.const_set("Rails", Struct.new(:root).new("/dummy/rails/app/"))
11
+ with_rails_defined do
13
12
  proxy = Defog::Proxy.new(args)
14
13
  proxy.proxy_root.should == Rails.root + "defog" + proxy.provider.to_s + proxy.location
15
- ensure
16
- Kernel.send :remove_const, "Rails"
17
14
  end
18
15
  end
19
16
 
@@ -23,6 +20,42 @@ shared_examples "a proxy" do |args|
23
20
  proxy.proxy_root.should == path
24
21
  end
25
22
 
23
+ context do
24
+ before(:each) do
25
+ @proxy = Defog::Proxy.new(args)
26
+ end
27
+
28
+ it "file should return a handle" do
29
+ handle = @proxy.file(key)
30
+ handle.proxy.should == @proxy
31
+ handle.key.should == key
32
+ end
33
+
34
+ it "file should yield a handle" do
35
+ ret = @proxy.file(key) do |handle|
36
+ handle.proxy.should == @proxy
37
+ handle.key.should == key
38
+ 123
39
+ end
40
+ ret.should == 123
41
+ end
42
+
43
+ it "should forward file open to handle" do
44
+ Defog::Handle.should_receive(:new).with(@proxy, key).and_return { mock('Handle').tap { |handle|
45
+ handle.should_receive(:open).with("r+", :persist => true)
46
+ } }
47
+ @proxy.file(key, "r+", :persist => true)
48
+ end
49
+
50
+ it "should return fog storage" do
51
+ @proxy.fog_connection.should == @proxy.fog_directory.connection
52
+ end
53
+
54
+ it "should return fog directory" do
55
+ create_remote("hello")
56
+ @proxy.fog_directory.files.get(key).body.should == "hello"
57
+ end
58
+ end
26
59
 
27
60
  end
28
61
 
data/spec/spec_helper.rb CHANGED
@@ -12,14 +12,15 @@ require 'defog'
12
12
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
13
13
 
14
14
  RSpec.configure do |config|
15
-
15
+ config.include Helpers
16
16
  end
17
17
 
18
18
  RSPEC_TMP_PATH = Pathname.new(__FILE__).dirname + "tmp"
19
19
  PROXY_BASE_PATH = RSPEC_TMP_PATH + "proxy"
20
20
  LOCAL_CLOUD_PATH = RSPEC_TMP_PATH + "cloud"
21
+ RAILS_ROOT_PATH = RSPEC_TMP_PATH + "railsapp"
21
22
 
22
- [PROXY_BASE_PATH, LOCAL_CLOUD_PATH].each do |path|
23
+ [PROXY_BASE_PATH, LOCAL_CLOUD_PATH, RAILS_ROOT_PATH].each do |path|
23
24
  path.rmtree if path.exist?
24
25
  path.mkpath
25
26
  end
@@ -0,0 +1,42 @@
1
+ module Helpers
2
+
3
+ def key
4
+ # returns a key that will be different for each example, to avoid any
5
+ # cross-example interactions
6
+ example.metadata[:full_description].gsub(/\+/,'plus').gsub(/\W/,'-') + "/filename"
7
+ end
8
+
9
+ def create_remote(body)
10
+ @proxy.fog_directory.files.create(:key => key, :body => body)
11
+ end
12
+
13
+ def proxy_path
14
+ @proxy.file(key).proxy_path
15
+ end
16
+
17
+ def create_proxy(body)
18
+ path = proxy_path
19
+ path.dirname.mkpath
20
+ path.open("w") do |f|
21
+ f.write(body)
22
+ end
23
+ end
24
+
25
+ def remote_body
26
+ @proxy.fog_directory.files.get(key).body
27
+ end
28
+
29
+ def remote_exist?
30
+ !!@proxy.fog_directory.files.head(key)
31
+ end
32
+
33
+ def with_rails_defined
34
+ begin
35
+ Kernel.const_set("Rails", Struct.new(:root).new(RAILS_ROOT_PATH))
36
+ yield
37
+ ensure
38
+ Kernel.send :remove_const, "Rails"
39
+ end
40
+ end
41
+
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: defog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-04-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
16
- requirement: &70247567066900 !ruby/object:Gem::Requirement
16
+ requirement: &70310792245820 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70247567066900
24
+ version_requirements: *70310792245820
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: hash_keyword_args
27
- requirement: &70247567066480 !ruby/object:Gem::Requirement
27
+ requirement: &70310792245400 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70247567066480
35
+ version_requirements: *70310792245400
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70247567066040 !ruby/object:Gem::Requirement
38
+ requirement: &70310792244960 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70247567066040
46
+ version_requirements: *70310792244960
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- requirement: &70247567065600 !ruby/object:Gem::Requirement
49
+ requirement: &70310792244520 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70247567065600
57
+ version_requirements: *70310792244520
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: simplecov
60
- requirement: &70247567065000 !ruby/object:Gem::Requirement
60
+ requirement: &70310792243920 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70247567065000
68
+ version_requirements: *70310792243920
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov-gem-adapter
71
- requirement: &70247567064460 !ruby/object:Gem::Requirement
71
+ requirement: &70310792243380 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70247567064460
79
+ version_requirements: *70310792243380
80
80
  description: Wrapper to fog gem, proxying access to cloud files as local files.
81
81
  email:
82
82
  - ronen@barzel.org
@@ -94,13 +94,15 @@ files:
94
94
  - lib/defog/error.rb
95
95
  - lib/defog/file.rb
96
96
  - lib/defog/fog_wrapper.rb
97
+ - lib/defog/handle.rb
97
98
  - lib/defog/proxy.rb
98
99
  - lib/defog/version.rb
99
100
  - spec/.gitignore
100
101
  - spec/file_spec.rb
102
+ - spec/handle_spec.rb
101
103
  - spec/proxy_spec.rb
102
104
  - spec/spec_helper.rb
103
- - spec/support/connections.rb
105
+ - spec/support/helpers.rb
104
106
  homepage: http://github.com/ronen/defog
105
107
  licenses: []
106
108
  post_install_message:
@@ -128,7 +130,8 @@ summary: Wrapper to fog gem, proxying access to cloud files as local files. Acc
128
130
  can be read-only (local cache), write-only (upload), or read-write (mirror)
129
131
  test_files:
130
132
  - spec/file_spec.rb
133
+ - spec/handle_spec.rb
131
134
  - spec/proxy_spec.rb
132
135
  - spec/spec_helper.rb
133
- - spec/support/connections.rb
136
+ - spec/support/helpers.rb
134
137
  has_rdoc:
File without changes