defog 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -41,7 +41,7 @@ object, which proxies files in a specific remote location, e.g.:
41
41
  :bucket => "s3-bucket-name")
42
42
 
43
43
  defog = Defog::Proxy.new(:provider => :Local,
44
- :directory => "/path/to/directory")
44
+ :local_root => "/path/to/directory")
45
45
 
46
46
  === Proxy a file
47
47
 
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 = opts.mode.match(re_encoding).to_s
60
- case opts.mode.sub(re_encoding,'')
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 #{opts.mode.inspect}"
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, opts.mode, &block)
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
@@ -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
- @local_root = Pathname.new(opts.local_root).realpath
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).content_md5
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
- # By default, each proxy's root directory is placed in a reasonable
30
- # safe place, under <code>Rails.root/tmp</code> if Rails is defined
31
- # otherwise under <code>Dir.tmpdir</code>. (More details: within that
32
- # directory, the root directory is disambiguated by #provider and
33
- # #location, so that multiple Defog::Proxy instances can be
34
- # created without collision.)
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.fog_directory.files.all.each do |fog_model|
140
- yield file(fog_model.key)
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
@@ -1,3 +1,3 @@
1
1
  module Defog
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
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
- Pathname.any_instance.should_not_receive(:open).with(/^w/)
27
- @proxy.file(key, @mode)
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 => (Rails.root + "public/defog").tap(&:mkpath))
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", 10)
62
- create_other_remote("i1", 10)
63
- create_other_remote("i2", 10)
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
- "#{key}-#{okey}"
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
 
@@ -23,11 +23,11 @@ module Helpers
23
23
  end
24
24
 
25
25
  def remote_body
26
- @proxy.fog_directory.files.get(key).body
26
+ @proxy.file(key).fog_model.body
27
27
  end
28
28
 
29
29
  def remote_exist?
30
- !!@proxy.fog_directory.files.head(key)
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.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-04-30 00:00:00.000000000 Z
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: &70345231086320 !ruby/object:Gem::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: *70345231086320
24
+ version_requirements: *70210590342260
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: hash_keyword_args
27
- requirement: &70345231085600 !ruby/object:Gem::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: *70345231085600
35
+ version_requirements: *70210590338240
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: fastandand
38
- requirement: &70345231084580 !ruby/object:Gem::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: *70345231084580
46
+ version_requirements: *70210590325960
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rake
49
- requirement: &70345231082860 !ruby/object:Gem::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: *70345231082860
57
+ version_requirements: *70210590316820
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
- requirement: &70345231005400 !ruby/object:Gem::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: *70345231005400
68
+ version_requirements: *70210590308480
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov
71
- requirement: &70345231001760 !ruby/object:Gem::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: *70345231001760
79
+ version_requirements: *70210590303920
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: simplecov-gem-adapter
82
- requirement: &70345231000720 !ruby/object:Gem::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: *70345231000720
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