defog 0.4.0 → 0.5.0
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.
- data/README.rdoc +1 -1
- data/lib/defog/file.rb +9 -4
- data/lib/defog/fog_wrapper.rb +27 -8
- data/lib/defog/handle.rb +9 -0
- data/lib/defog/proxy.rb +25 -9
- data/lib/defog/version.rb +1 -1
- data/spec/file_spec.rb +10 -8
- data/spec/handle_spec.rb +5 -1
- data/spec/proxy_spec.rb +37 -5
- data/spec/support/helpers.rb +2 -2
- metadata +16 -16
data/README.rdoc
CHANGED
data/lib/defog/file.rb
CHANGED
@@ -51,13 +51,14 @@ module Defog
|
|
51
51
|
@handle = opts.handle
|
52
52
|
@persist = opts.persist
|
53
53
|
@synchronize = opts.synchronize
|
54
|
+
@mode = opts.mode
|
54
55
|
|
55
56
|
key = @handle.key
|
56
57
|
proxy_path = @handle.proxy_path
|
57
58
|
proxy_path.dirname.mkpath
|
58
59
|
re_encoding = /(b|:.*)$/
|
59
|
-
@encoding =
|
60
|
-
case
|
60
|
+
@encoding = @mode.match(re_encoding).to_s
|
61
|
+
case @mode.sub(re_encoding,'')
|
61
62
|
when "r"
|
62
63
|
download = true
|
63
64
|
@upload = false
|
@@ -71,13 +72,17 @@ module Defog
|
|
71
72
|
@upload = true
|
72
73
|
cache_size = [opts.size_hint, @handle.size].compact.max
|
73
74
|
else
|
74
|
-
raise ArgumentError, "Invalid mode #{
|
75
|
+
raise ArgumentError, "Invalid mode #{@mode.inspect}"
|
75
76
|
end
|
76
77
|
|
77
78
|
@handle.proxy.manage_cache(cache_size, proxy_path)
|
78
79
|
@handle.proxy.reserve_proxy_path(proxy_path)
|
79
80
|
download_proxy if download
|
80
|
-
super(proxy_path,
|
81
|
+
super(proxy_path, @mode, &block)
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_s
|
85
|
+
"<#{self.class}: proxy=#{@handle.proxy_path} mode=#{@mode}>"
|
81
86
|
end
|
82
87
|
|
83
88
|
# Closes the proxy file and synchronizes the cloud storage (if it was
|
data/lib/defog/fog_wrapper.rb
CHANGED
@@ -5,6 +5,7 @@ require "pathname"
|
|
5
5
|
module Defog #:nodoc: all
|
6
6
|
class FogWrapper #:nodoc: all
|
7
7
|
|
8
|
+
attr_reader :prefix
|
8
9
|
attr_reader :location
|
9
10
|
attr_reader :fog_connection
|
10
11
|
attr_reader :fog_directory
|
@@ -31,22 +32,39 @@ module Defog #:nodoc: all
|
|
31
32
|
def put_file(key, path, encoding)
|
32
33
|
return if path.exist? and fog_head(key) and Digest::MD5.hexdigest(path.read) == get_md5(key)
|
33
34
|
path.open("r#{encoding}") do |file|
|
34
|
-
fog_directory.files.create(:key => key, :body => file)
|
35
|
+
fog_directory.files.create(:key => @prefix.to_s + key, :body => file)
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
39
|
def fog_head(key)
|
39
|
-
fog_directory.files.head(key)
|
40
|
+
fog_directory.files.head(@prefix.to_s + key)
|
41
|
+
end
|
42
|
+
|
43
|
+
def each
|
44
|
+
prefix = @prefix.to_s
|
45
|
+
off = prefix.size
|
46
|
+
@fog_directory.files.all.each do |fog_model|
|
47
|
+
yield fog_model.key[off .. -1] if fog_model.key.start_with? prefix
|
48
|
+
end
|
40
49
|
end
|
41
50
|
|
42
51
|
private
|
43
52
|
|
53
|
+
def initialize(opts={})
|
54
|
+
opts = opts.keyword_args(:prefix => :optional)
|
55
|
+
@prefix = opts.prefix
|
56
|
+
end
|
57
|
+
|
58
|
+
|
44
59
|
class Local < FogWrapper
|
45
60
|
def provider ; :local ; end
|
46
61
|
|
47
62
|
def initialize(opts={})
|
48
|
-
opts = opts.keyword_args(:local_root => :required)
|
49
|
-
|
63
|
+
opts = opts.keyword_args(:local_root => :required, :prefix => :optional)
|
64
|
+
super(:prefix => opts.delete(:prefix))
|
65
|
+
@local_root = Pathname.new(opts.local_root)
|
66
|
+
@local_root.mkpath unless @local_root.exist?
|
67
|
+
@local_root = @local_root.realpath
|
50
68
|
@location = @local_root.to_s.gsub(%r{/},'-')
|
51
69
|
@fog_connection = Fog::Storage.new(:provider => provider, :local_root => @local_root)
|
52
70
|
@fog_directory = @fog_connection.directories.get('.')
|
@@ -57,7 +75,7 @@ module Defog #:nodoc: all
|
|
57
75
|
end
|
58
76
|
|
59
77
|
def url(key, expiry)
|
60
|
-
localpath = Pathname.new("#{@local_root}/#{key}").expand_path
|
78
|
+
localpath = Pathname.new("#{@local_root}/#{@prefix}#{key}").expand_path
|
61
79
|
if defined?(Rails)
|
62
80
|
relative = localpath.relative_path_from Rails.root + "public" rescue nil
|
63
81
|
return "/" + relative.to_s if relative and not relative.to_s.start_with? "../"
|
@@ -71,15 +89,16 @@ module Defog #:nodoc: all
|
|
71
89
|
def provider ; :AWS ; end
|
72
90
|
|
73
91
|
def initialize(opts={})
|
74
|
-
opts = opts.keyword_args(:aws_access_key_id => :required, :aws_secret_access_key => :required, :region => :optional, :bucket => :required)
|
92
|
+
opts = opts.keyword_args(:aws_access_key_id => :required, :aws_secret_access_key => :required, :region => :optional, :bucket => :required, :prefix => :optional)
|
93
|
+
super(:prefix => opts.delete(:prefix))
|
75
94
|
@location = opts.delete(:bucket)
|
76
95
|
@fog_connection = (@@aws_connection_cache||={})[opts] ||= Fog::Storage.new(opts.merge(:provider => provider))
|
77
96
|
@fog_connection.directories.create :key => @location unless @fog_connection.directories.map(&:key).include? @location
|
78
|
-
@fog_directory = @fog_connection.directories.get(@location)
|
97
|
+
@fog_directory = @fog_connection.directories.get(@location, :prefix => @prefix)
|
79
98
|
end
|
80
99
|
|
81
100
|
def get_md5(key)
|
82
|
-
fog_head(key).
|
101
|
+
fog_head(key).etag
|
83
102
|
end
|
84
103
|
|
85
104
|
def url(key, expiry)
|
data/lib/defog/handle.rb
CHANGED
@@ -35,6 +35,10 @@ module Defog
|
|
35
35
|
@proxy_path = Pathname.new("#{@proxy.proxy_root}/#{@key}").expand_path
|
36
36
|
end
|
37
37
|
|
38
|
+
def to_s
|
39
|
+
"<#{self.class}: key=#{key}>"
|
40
|
+
end
|
41
|
+
|
38
42
|
# Returns true if the remote cloud file exists
|
39
43
|
def exist?
|
40
44
|
!!fog_model
|
@@ -72,6 +76,11 @@ module Defog
|
|
72
76
|
end
|
73
77
|
|
74
78
|
# Returns the underlying Fog::Model, should you need it for something.
|
79
|
+
# Returns nil if the model doesn't exist.
|
80
|
+
#
|
81
|
+
# If Defog::Proxy.new was passed a :prefix, the Fog::Model key and
|
82
|
+
# Defog::Handle key are related by:
|
83
|
+
# handle.fog_model.key == defog.prefix + handle.key
|
75
84
|
def fog_model
|
76
85
|
@proxy.fog_wrapper.fog_head(@key)
|
77
86
|
end
|
data/lib/defog/proxy.rb
CHANGED
@@ -26,12 +26,19 @@ module Defog
|
|
26
26
|
# the same access info but different buckets; they will internally
|
27
27
|
# share a single Fog::Storage isntance hence AWS connection.)
|
28
28
|
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
29
|
+
# To further restrict the remote files acted on by this proxy, you
|
30
|
+
# can specify
|
31
|
+
# defog = Defog::Proxy.new(:provider => ..., :prefix => "my-prefix-string/")
|
32
|
+
# and all keys that you pass to Defog will be prefixed with the given
|
33
|
+
# string before being passed along to Fog. (Notice that it's up to you to
|
34
|
+
# have a trailing "/" in the prefix if that's what you want.)
|
35
|
+
#
|
36
|
+
# By default, each proxy's cache root directory is placed in a
|
37
|
+
# reasonable safe place, under <code>Rails.root/tmp</code> if Rails is
|
38
|
+
# defined otherwise under <code>Dir.tmpdir</code>. (More details:
|
39
|
+
# within that directory, the root directory is disambiguated by
|
40
|
+
# #provider and #location, so that multiple Defog::Proxy instances can
|
41
|
+
# be created without collision.)
|
35
42
|
#
|
36
43
|
# The upshot is that if you have no special constraints you don't need
|
37
44
|
# to worry about it. But if you do care, you can specify the option:
|
@@ -84,6 +91,10 @@ module Defog
|
|
84
91
|
|
85
92
|
end
|
86
93
|
|
94
|
+
def to_s
|
95
|
+
"<#{self.class} provider=#{provider} location=#{location}>"
|
96
|
+
end
|
97
|
+
|
87
98
|
# Returns the provider for this proxy. I.e., <code>:local</code> or
|
88
99
|
# <code>:AWS</code>
|
89
100
|
def provider
|
@@ -108,6 +119,11 @@ module Defog
|
|
108
119
|
@fog_wrapper.fog_directory
|
109
120
|
end
|
110
121
|
|
122
|
+
# Returns the prefix that was passed
|
123
|
+
def prefix
|
124
|
+
@fog_wrapper.prefix
|
125
|
+
end
|
126
|
+
|
111
127
|
# Proxy a remote cloud file. Returns or yields a Defog::Handle object that
|
112
128
|
# represents the file.
|
113
129
|
#
|
@@ -134,10 +150,10 @@ module Defog
|
|
134
150
|
# remote file.
|
135
151
|
#
|
136
152
|
# If no block is given, an enumerator is returned.
|
137
|
-
def each
|
153
|
+
def each(&block)
|
138
154
|
if block_given?
|
139
|
-
@fog_wrapper.
|
140
|
-
yield file(
|
155
|
+
@fog_wrapper.each do |key|
|
156
|
+
yield file(key)
|
141
157
|
end
|
142
158
|
else
|
143
159
|
to_enum(:each)
|
data/lib/defog/version.rb
CHANGED
data/spec/file_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
shared_examples "get proxy" do
|
4
|
+
|
4
5
|
it "should create proxy if remote exists" do
|
5
6
|
create_remote("hello")
|
6
7
|
file = @proxy.file(key, @mode)
|
@@ -23,14 +24,9 @@ shared_examples "get proxy" do
|
|
23
24
|
it "should use existing proxy if it's valid" do
|
24
25
|
create_remote("hello")
|
25
26
|
create_proxy("hello")
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# doublecheck that should_not_receive was the right
|
30
|
-
# thing to test. will it be received for an invalid proxy?
|
31
|
-
create_proxy("goodbye")
|
32
|
-
Pathname.any_instance.should_receive(:open).with(/^w/)
|
33
|
-
@proxy.file(key, @mode)
|
27
|
+
handle = @proxy.file(key)
|
28
|
+
handle.proxy_path.should_not_receive(:open).with(/^w/)
|
29
|
+
handle.open(@mode)
|
34
30
|
end
|
35
31
|
end
|
36
32
|
|
@@ -240,6 +236,12 @@ shared_examples "a proxy file" do |proxyargs|
|
|
240
236
|
expect { @proxy.file(key, "xyz") }.should raise_error(ArgumentError)
|
241
237
|
end
|
242
238
|
|
239
|
+
it "should have a nice to_s" do
|
240
|
+
@proxy.file(key, "w") {|f|
|
241
|
+
f.to_s.should include f.path
|
242
|
+
}
|
243
|
+
end
|
244
|
+
|
243
245
|
|
244
246
|
end
|
245
247
|
|
data/spec/handle_spec.rb
CHANGED
@@ -10,6 +10,10 @@ shared_examples "a handle" do |proxyargs|
|
|
10
10
|
@handle = @proxy.file(key)
|
11
11
|
end
|
12
12
|
|
13
|
+
it "should have a nice to_s" do
|
14
|
+
@handle.to_s.should include key
|
15
|
+
end
|
16
|
+
|
13
17
|
it "should report exist? true if remote cloud file exists" do
|
14
18
|
create_remote("i exist")
|
15
19
|
@handle.should be_exist
|
@@ -80,7 +84,7 @@ describe Defog::Handle do
|
|
80
84
|
|
81
85
|
it "should return a path relative to public if in public" do
|
82
86
|
with_rails_defined do
|
83
|
-
@proxy = Defog::Proxy.new(:provider => :local, :local_root =>
|
87
|
+
@proxy = Defog::Proxy.new(:provider => :local, :local_root => Rails.root + "public/defog")
|
84
88
|
@proxy.file(key).url.should == "/defog/#{key}"
|
85
89
|
end
|
86
90
|
end
|
data/spec/proxy_spec.rb
CHANGED
@@ -7,6 +7,11 @@ shared_examples "a proxy" do |args|
|
|
7
7
|
@proxy = Defog::Proxy.new(args)
|
8
8
|
end
|
9
9
|
|
10
|
+
it "should have a nice to_s" do
|
11
|
+
@proxy.to_s.should include @proxy.provider.to_s
|
12
|
+
@proxy.to_s.should include @proxy.location
|
13
|
+
end
|
14
|
+
|
10
15
|
it "file should return a handle" do
|
11
16
|
handle = @proxy.file(key)
|
12
17
|
handle.proxy.should == @proxy
|
@@ -58,9 +63,9 @@ shared_examples "a proxy" do |args|
|
|
58
63
|
before(:each) do
|
59
64
|
@proxy = Defog::Proxy.new(args)
|
60
65
|
@proxy.fog_directory.files.all.each do |model| model.destroy end
|
61
|
-
create_other_remote("i0"
|
62
|
-
create_other_remote("i1"
|
63
|
-
create_other_remote("i2"
|
66
|
+
create_other_remote("i0")
|
67
|
+
create_other_remote("i1")
|
68
|
+
create_other_remote("i2")
|
64
69
|
end
|
65
70
|
|
66
71
|
it "should iterate through remotes" do
|
@@ -77,6 +82,33 @@ shared_examples "a proxy" do |args|
|
|
77
82
|
|
78
83
|
end
|
79
84
|
|
85
|
+
context "prefix" do
|
86
|
+
it "should return its prefix" do
|
87
|
+
prefix = "me-first"
|
88
|
+
@proxy = Defog::Proxy.new(args.merge(:prefix => prefix))
|
89
|
+
@proxy.prefix.should == prefix
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should use a prefix" do
|
93
|
+
prefix = "me-first"
|
94
|
+
@proxy = Defog::Proxy.new(args.merge(:prefix => prefix))
|
95
|
+
@proxy.file(key, "w") { |f| f.puts "hello" }
|
96
|
+
@proxy.file(key).fog_model.key.should == prefix + key
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should iterate only matches to prefix" do
|
100
|
+
@proxy = Defog::Proxy.new(args.merge(:prefix => "yes-"))
|
101
|
+
@proxy.fog_directory.files.all.each do |model| model.destroy end
|
102
|
+
create_other_remote("no-n1")
|
103
|
+
create_other_remote("no-n2")
|
104
|
+
create_other_remote("no-n3")
|
105
|
+
create_other_remote("yes-y1")
|
106
|
+
create_other_remote("yes-y2")
|
107
|
+
create_other_remote("yes-y3")
|
108
|
+
@proxy.each.map(&:key).should =~[other_key("y1"), other_key("y2"), other_key("y3")]
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
80
112
|
|
81
113
|
context "proxy root location" do
|
82
114
|
it "should default proxy root to tmpdir/defog" do
|
@@ -197,7 +229,7 @@ shared_examples "a proxy" do |args|
|
|
197
229
|
private
|
198
230
|
|
199
231
|
def other_key(okey)
|
200
|
-
"#{
|
232
|
+
"#{okey}-#{key}"
|
201
233
|
end
|
202
234
|
|
203
235
|
def create_other_proxy(okey, size)
|
@@ -212,7 +244,7 @@ shared_examples "a proxy" do |args|
|
|
212
244
|
@proxy.file(other_key(okey)).proxy_path
|
213
245
|
end
|
214
246
|
|
215
|
-
def create_other_remote(okey, size)
|
247
|
+
def create_other_remote(okey, size=10)
|
216
248
|
@proxy.fog_directory.files.create(:key => other_key(okey), :body => "x" * size)
|
217
249
|
end
|
218
250
|
|
data/spec/support/helpers.rb
CHANGED
@@ -23,11 +23,11 @@ module Helpers
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def remote_body
|
26
|
-
@proxy.
|
26
|
+
@proxy.file(key).fog_model.body
|
27
27
|
end
|
28
28
|
|
29
29
|
def remote_exist?
|
30
|
-
|
30
|
+
@proxy.file(key).exist?
|
31
31
|
end
|
32
32
|
|
33
33
|
def with_rails_defined
|
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.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
16
|
-
requirement: &
|
16
|
+
requirement: &70210590342260 !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: *
|
24
|
+
version_requirements: *70210590342260
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: hash_keyword_args
|
27
|
-
requirement: &
|
27
|
+
requirement: &70210590338240 !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: *
|
35
|
+
version_requirements: *70210590338240
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: fastandand
|
38
|
-
requirement: &
|
38
|
+
requirement: &70210590325960 !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: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70210590325960
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rake
|
49
|
-
requirement: &
|
49
|
+
requirement: &70210590316820 !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: *
|
57
|
+
version_requirements: *70210590316820
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rspec
|
60
|
-
requirement: &
|
60
|
+
requirement: &70210590308480 !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: *
|
68
|
+
version_requirements: *70210590308480
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: simplecov
|
71
|
-
requirement: &
|
71
|
+
requirement: &70210590303920 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70210590303920
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: simplecov-gem-adapter
|
82
|
-
requirement: &
|
82
|
+
requirement: &70210590295300 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70210590295300
|
91
91
|
description: Wrapper to fog gem, proxying access to cloud files as local files.
|
92
92
|
email:
|
93
93
|
- ronen@barzel.org
|