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