fluffy 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ *.gem
7
+ demo*
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Ben Wyrosdick
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ = fluffy
2
+
3
+ Description goes here.
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2009 Ben Wyrosdick. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "fluffy"
8
+ gem.summary = %Q{TODO}
9
+ gem.email = "ben.wyrosdick@gmail.com"
10
+ gem.homepage = "http://github.com/commonthread/fluffy"
11
+ gem.authors = ["Ben Wyrosdick"]
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/*_test.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+ begin
40
+ require 'cucumber/rake/task'
41
+ Cucumber::Rake::Task.new(:features)
42
+ rescue LoadError
43
+ task :features do
44
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
45
+ end
46
+ end
47
+
48
+ task :default => :test
49
+
50
+ require 'rake/rdoctask'
51
+ Rake::RDocTask.new do |rdoc|
52
+ if File.exist?('VERSION.yml')
53
+ config = YAML.load(File.read('VERSION.yml'))
54
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
55
+ else
56
+ version = ""
57
+ end
58
+
59
+ rdoc.rdoc_dir = 'rdoc'
60
+ rdoc.title = "fluffy #{version}"
61
+ rdoc.rdoc_files.include('README*')
62
+ rdoc.rdoc_files.include('lib/**/*.rb')
63
+ end
64
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,9 @@
1
+ Feature: something something
2
+ In order to something something
3
+ A user something something
4
+ something something something
5
+
6
+ Scenario: something something
7
+ Given inspiration
8
+ When I create a sweet new gem
9
+ Then everyone should see how awesome I am
File without changes
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'fluffy'
3
+
4
+ require 'test/unit/assertions'
5
+
6
+ World(Test::Unit::Assertions)
data/fluffy.gemspec ADDED
@@ -0,0 +1,51 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{fluffy}
5
+ s.version = "0.1.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Ben Wyrosdick"]
9
+ s.date = %q{2009-07-24}
10
+ s.email = %q{ben@commonthread.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "features/fluffy.feature",
23
+ "features/step_definitions/fluffy_steps.rb",
24
+ "features/support/env.rb",
25
+ "fluffy.gemspec",
26
+ "lib/fluffy.rb",
27
+ "lib/fluffy/s3_io.rb",
28
+ "lib/fluffy/s3_path.rb",
29
+ "test/fluffy_test.rb",
30
+ "test/test_helper.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/commonthread/fluffy}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.4}
36
+ s.summary = %q{Makes writing to S3 tranparent using File}
37
+ s.test_files = [
38
+ "test/fluffy_test.rb",
39
+ "test/test_helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ else
48
+ end
49
+ else
50
+ end
51
+ end
data/lib/fluffy.rb ADDED
@@ -0,0 +1,330 @@
1
+ require File.join(File.dirname(__FILE__), 'fluffy/s3_path')
2
+ require File.join(File.dirname(__FILE__), 'fluffy/s3_io')
3
+
4
+ require 'right_aws'
5
+ require 'fileutils'
6
+ require 'pathname'
7
+
8
+ RealFile = File
9
+ #RealFileUtils = FileUtils
10
+ RealDir = Dir
11
+ #RealFileUtils::Dir = RealDir
12
+ #RealFileUtils::File = RealFile
13
+
14
+ module Fluffy
15
+ #module FileUtils
16
+ # extend self
17
+
18
+ # def mkdir_p(path)
19
+ # RealFileUtils.mkdir_p(path)
20
+ # end
21
+
22
+ # def rm(path)
23
+ # RealFileUtils.rm(path)
24
+ # end
25
+
26
+ # def rm_r(path)
27
+ # RealFileUtils.rm_r(path)
28
+ # end
29
+
30
+ # def rm_rf(path)
31
+ # RealFileUtils.rm_rf(path)
32
+ # end
33
+
34
+ # def ln_s(target, path)
35
+ # raise Errno::EEXIST, path if File.exists?(path)
36
+ # RealFileUtils.ln_s(target, path)
37
+ # end
38
+
39
+ # def cp(src, dest)
40
+ # RealFileUtils.cp(src, dest)
41
+ # #dst_file = FileSystem.find(dest)
42
+ # #src_file = FileSystem.find(src)
43
+
44
+ # #if !src_file
45
+ # # raise Errno::ENOENT, src
46
+ # #end
47
+
48
+ # #if File.directory? src_file
49
+ # # raise Errno::EISDIR, src
50
+ # #end
51
+
52
+ # #if dst_file and File.directory?(dst_file)
53
+ # # FileSystem.add(File.join(dest, src), src_file.entry.clone(dst_file))
54
+ # #else
55
+ # # FileSystem.delete(dest)
56
+ # # FileSystem.add(dest, src_file.entry.clone)
57
+ # #end
58
+ # end
59
+
60
+ # def cp_r(src, dest)
61
+ # RealFileUtils.cp_r(src, dest)
62
+ # ## This error sucks, but it conforms to the original Ruby
63
+ # ## method.
64
+ # #raise "unknown file type: #{src}" unless dir = FileSystem.find(src)
65
+
66
+ # #new_dir = FileSystem.find(dest)
67
+
68
+ # #if new_dir && !File.directory?(dest)
69
+ # # raise Errno::EEXIST, dest
70
+ # #end
71
+
72
+ # #if !new_dir && !FileSystem.find(dest+'/../')
73
+ # # raise Errno::ENOENT, dest
74
+ # #end
75
+
76
+ # ## This last bit is a total abuse and should be thought hard
77
+ # ## about and cleaned up.
78
+ # #if new_dir
79
+ # # if src[-2..-1] == '/.'
80
+ # # dir.values.each{|f| new_dir[f.name] = f.clone(new_dir) }
81
+ # # else
82
+ # # new_dir[dir.name] = dir.entry.clone(new_dir)
83
+ # # end
84
+ # #else
85
+ # # FileSystem.add(dest, dir.entry.clone)
86
+ # #end
87
+ # end
88
+
89
+ # def mv(src, dest)
90
+ # RealFileUtils.mv(src, dest)
91
+ # #if target = FileSystem.find(src)
92
+ # # FileSystem.add(dest, target.entry.clone)
93
+ # # FileSystem.delete(src)
94
+ # #else
95
+ # # raise Errno::ENOENT, src
96
+ # #end
97
+ # end
98
+
99
+ # def chown(user, group, list, options={})
100
+ # RealFileUtils.chown(user, group, list, options)
101
+ # #list = Array(list)
102
+ # #list.each do |f|
103
+ # # unless File.exists?(f)
104
+ # # raise Errno::ENOENT, f
105
+ # # end
106
+ # #end
107
+ # #list
108
+ # end
109
+
110
+ # def chown_R(user, group, list, options={})
111
+ # RealFileUtils.chown_R(user, group, list, options={})
112
+ # #chown(user, group, list, options={})
113
+ # end
114
+
115
+ # def touch(list, options={})
116
+ # RealFileUtils.touch(list, options)
117
+ # #Array(list).each do |f|
118
+ # # directory = File.dirname(f)
119
+ # # # FIXME this explicit check for '.' shouldn't need to happen
120
+ # # if File.exists?(directory) || directory == '.'
121
+ # # FileSystem.add(f, MockFile.new)
122
+ # # else
123
+ # # raise Errno::ENOENT, f
124
+ # # end
125
+ # #end
126
+ # end
127
+
128
+ # def cd(dir)
129
+ # RealFileUtils.cd(dir)
130
+ # end
131
+ # alias_method :chdir, :cd
132
+
133
+ # def method_missing(meth, *args, &block)
134
+ # RealFileUtils.send(meth, *args, &block)
135
+ # end
136
+ #end
137
+
138
+ class File
139
+ PATH_SEPARATOR = '/'
140
+
141
+ @@s3_paths = []
142
+
143
+ def self.register_s3(file_path, access_key_id, secret_access_key, bucket, start_path = '')
144
+ File.s3_paths << Fluffy::S3Path.new(File.expand_path(file_path), access_key_id, secret_access_key, bucket, start_path)
145
+ end
146
+
147
+ def self.s3_paths
148
+ return @@s3_paths
149
+ end
150
+
151
+ def self.join(*parts)
152
+ RealFile.join(parts)
153
+ end
154
+
155
+ def self.exist?(path)
156
+ Fluffy.cloud_runner(RealFile, :exist?, path) do |s3_path, key|
157
+ s3_path.bucket.key(key).exists? or self.directory?(path)
158
+ end
159
+ end
160
+
161
+ def self.const_missing(name)
162
+ RealFile.const_get(name)
163
+ end
164
+
165
+ class << self
166
+ alias_method :exists?, :exist?
167
+ end
168
+
169
+ def self.directory?(path)
170
+ Fluffy.cloud_runner(RealFile, :directory?, path) do |s3_path, key|
171
+ s3_path.bucket.keys('prefix' => key).map{|k| k.name}.any?{|keyname| keyname[key.length] && keyname[key.length].chr == '/'}
172
+ end
173
+ end
174
+
175
+ def self.symlink?(path)
176
+ RealFile.symlink?(path)
177
+ end
178
+
179
+ def self.file?(path)
180
+ RealFile.file?(path)
181
+ end
182
+
183
+ def self.expand_path(*args)
184
+ RealFile.expand_path(*args)
185
+ end
186
+
187
+ def self.basename(*args)
188
+ RealFile.basename(*args)
189
+ end
190
+
191
+ def self.dirname(path)
192
+ RealFile.dirname(path)
193
+ end
194
+
195
+ def self.readlink(path)
196
+ RealFile.readlink(path)
197
+ end
198
+
199
+ def self.open(path, mode='r', &block)
200
+ Fluffy.cloud_runner(RealFile, :open, path, block) do |s3_path, key|
201
+ s3io = Fluffy::S3Io.new(s3_path, key, mode)
202
+
203
+ if block_given?
204
+ block_val = yield(s3io)
205
+ s3io.close
206
+ return block_val
207
+ end
208
+
209
+ return s3io
210
+ end
211
+ end
212
+
213
+ def self.read(path)
214
+ open(path).read
215
+ end
216
+
217
+ def self.readlines(path)
218
+ open(path).readlines
219
+ end
220
+
221
+ def self.unlink(*filepaths)
222
+ filepaths.each do |filename|
223
+ Fluffy.cloud_runner(RealFile, :unlink, filename) do |s3_path, key|
224
+ s3_path.bucket.key(key).delete
225
+ end
226
+ end
227
+ end
228
+
229
+ def self.new(path, mode = nil)
230
+ Fluffy.cloud_runner(RealFile, :new, path) do |s3_path, key|
231
+ open(path, mode)
232
+ end
233
+ end
234
+
235
+ def self.chmod(mode, *files)
236
+ #FIXME: Make it work
237
+ end
238
+
239
+ def self.method_missing(meth, *args, &block)
240
+ RealFile.send(meth, *args, &block)
241
+ end
242
+ end
243
+
244
+ class Dir
245
+ def self.glob(pattern)
246
+ RealDir.glob(pattern)
247
+ #if pattern[-1,1] == '*'
248
+ # blk = proc { |entry| entry.to_s }
249
+ #else
250
+ # blk = proc { |entry| entry[1].parent.to_s }
251
+ #end
252
+ #(FileSystem.find(pattern) || []).map(&blk).uniq.sort
253
+ end
254
+
255
+ def self.[](pattern)
256
+ glob(pattern)
257
+ end
258
+
259
+ def self.entries(path)
260
+ RealDir.entries(path)
261
+ end
262
+
263
+ def self.chdir(dir, &blk)
264
+ RealDir.chdir(dir, blk)
265
+ end
266
+
267
+ def self.unlink(dirpath)
268
+ Fluffy.cloud_runner(self, :unlink, dirpath) do |s3_path, key|
269
+ s3_path.bucket.key(key).delete
270
+ end
271
+ end
272
+
273
+ class << self
274
+ alias_method :rmdir, :unlink
275
+ alias_method :delete, :unlink
276
+ end
277
+
278
+ def self.method_missing(meth, *args, &block)
279
+ RealDir.send(meth, *args, &block)
280
+ end
281
+ end
282
+
283
+ def self.cloud_runner(klass, method_name, filename, method_block=nil, &block)
284
+ expanded_filename = File.expand_path(filename)
285
+ if s3_path = File.s3_paths.find {|path| expanded_filename =~ /^#{path.file_path}/}
286
+ starting_position = s3_path.file_path.length + 1
287
+ if expanded_filename.length > starting_position
288
+ key = expanded_filename[starting_position .. -1]
289
+ yield(s3_path, File.join(s3_path.start_path, key).gsub(/^\W/, ''))
290
+ elsif method_name == :directory?
291
+ return true
292
+ else
293
+ raise 'You must specify a key'
294
+ end
295
+ else
296
+ klass.send(method_name, filename, &method_block)
297
+ end
298
+ end
299
+ end
300
+
301
+ Object.class_eval do
302
+ remove_const(:Dir)
303
+ remove_const(:File)
304
+ #remove_const(:FileUtils)
305
+ end
306
+
307
+ #FileUtils = Fluffy::FileUtils
308
+ File = Fluffy::File
309
+ Dir = Fluffy::Dir
310
+
311
+ ## File
312
+ #
313
+ # lchmod
314
+ # lchown
315
+ # lstat
316
+ # chmod
317
+ # chown
318
+ # stat
319
+ # utime
320
+ # directory?
321
+ # rename
322
+ # unlink
323
+ # symlink
324
+
325
+ ## Dir
326
+ #
327
+ # []
328
+ # mkdir
329
+ # entries
330
+ # glob
@@ -0,0 +1,104 @@
1
+ module Fluffy
2
+ class S3Io < IO
3
+ attr_accessor :s3_path, :s3, :bucket, :key, :data, :mode, :pos
4
+ attr_reader :read_mode, :write_mode
5
+
6
+ def initialize(s3_path, key, mode)
7
+ self.s3_path = s3_path
8
+ self.key = self.s3_path.bucket.key(key)
9
+ self.data = self.key.data || ''
10
+ self.mode = mode
11
+
12
+ case self.mode.gsub(/b/, '') # We ignore the binary flag at this time
13
+ when 'r', 'r+'
14
+ self.pos = 0
15
+ @read_mode = true
16
+ @write_mode = !!(self.mode =~ /\+/)
17
+ when 'w', 'w+'
18
+ self.data = ''
19
+ self.pos = 0
20
+ @read_mode = !!(self.mode =~ /\+/)
21
+ @write_mode = true
22
+ when 'a', 'a+'
23
+ self.pos = self.data.length
24
+ @read_mode = !!(self.mode =~ /\+/)
25
+ @write_mode = true
26
+ end
27
+ end
28
+
29
+ def eof
30
+ eof?
31
+ end
32
+
33
+ def eof?
34
+ self.pos >= self.data.length
35
+ end
36
+
37
+ def each(&block)
38
+ until self.eof?
39
+ yield(self.gets)
40
+ end
41
+ end
42
+
43
+ def each_line(&block)
44
+ self.each(block)
45
+ end
46
+
47
+ def read(length = nil)
48
+ if length
49
+ return nil if self.eof?
50
+ data = self.data[self.pos, length]
51
+ self.pos += length
52
+ else
53
+ data = self.data[self.pos .. -1]
54
+ self.pos = self.data.length
55
+ end
56
+
57
+ return data
58
+ end
59
+
60
+ def write(string = nil)
61
+ string ||= $_
62
+ string << $\ if $\
63
+ self.data[self.pos, string.length] = string
64
+ self.pos += string.length
65
+ return nil
66
+ end
67
+ alias_method :print, :write
68
+ alias_method :<<, :write
69
+
70
+ def puts(*strings)
71
+ strings.each do |string|
72
+ string << "\n" unless string =~ /\n$/
73
+ self.print(string)
74
+ end
75
+ self.flush
76
+ return nil
77
+ end
78
+
79
+ def readline
80
+ self.gets
81
+ end
82
+
83
+ def readlines
84
+ return self.data.split("\n")
85
+ end
86
+
87
+ def gets(sep_string = "\n")
88
+ sep_string = "\n\n" if sep_string == ''
89
+
90
+ end_pos = self.data.index(sep_string, self.pos) || self.data.length
91
+
92
+ $_ = self.read(end_pos - self.pos + 1)
93
+ end
94
+
95
+ def close
96
+ flush
97
+ end
98
+
99
+ def flush
100
+ self.key.put(self.data)
101
+ self
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,14 @@
1
+ module Fluffy
2
+ class S3Path
3
+ attr_accessor :file_path, :access_key_id, :secret_access_key, :bucket, :start_path, :s3
4
+
5
+ def initialize(file_path, access_key_id, secret_access_key, bucket, start_path = '')
6
+ self.file_path = file_path
7
+ self.access_key_id = access_key_id
8
+ self.secret_access_key = secret_access_key
9
+ self.s3 = RightAws::S3.new(self.access_key_id, self.secret_access_key)
10
+ self.bucket = self.s3.bucket(bucket)
11
+ self.start_path = start_path
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class FluffyTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'fluffy'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluffy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Ben Wyrosdick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-24 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: ben@commonthread.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README.rdoc
30
+ - Rakefile
31
+ - VERSION
32
+ - features/fluffy.feature
33
+ - features/step_definitions/fluffy_steps.rb
34
+ - features/support/env.rb
35
+ - fluffy.gemspec
36
+ - lib/fluffy.rb
37
+ - lib/fluffy/s3_io.rb
38
+ - lib/fluffy/s3_path.rb
39
+ - test/fluffy_test.rb
40
+ - test/test_helper.rb
41
+ has_rdoc: true
42
+ homepage: http://github.com/commonthread/fluffy
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options:
47
+ - --charset=UTF-8
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.4
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Makes writing to S3 tranparent using File
69
+ test_files:
70
+ - test/fluffy_test.rb
71
+ - test/test_helper.rb