cabinet 0.1.3 → 0.2.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.
@@ -0,0 +1,121 @@
1
+ module Cabinet
2
+ class Instance
3
+ attr_accessor :connection, :directory
4
+
5
+ def initialize(provider, auth={})
6
+ fog_config = auth.merge({:provider => fog_provider(provider)})
7
+ self.connection = Fog::Storage.new(fog_config)
8
+ end
9
+
10
+ def directory=(name)
11
+ @directory = connection.directories.get(name) || connection.directories.create(:key => name)
12
+ end
13
+
14
+ alias :container= :directory=
15
+ alias :bucket= :directory=
16
+
17
+ def get(name)
18
+ file(name).body
19
+ end
20
+
21
+ def list(regexp=/.*/)
22
+ directory.files.reload
23
+ directory.files.select{|f| f.key.match(regexp)}.to_a.map(&:key)
24
+ end
25
+
26
+ def put(name, content)
27
+ content = content.to_s
28
+
29
+ begin
30
+ directory.files.create(:key => name, :body => content).content_length == content.length
31
+ rescue
32
+ false
33
+ end
34
+ end
35
+
36
+ def touch(name)
37
+ (exists?(name) ? put(name, get(name)) : put(name, "")) and !!reload(name)
38
+ end
39
+
40
+ def append(name, new_content)
41
+ content = exists?(name) ? get(name) + new_content : new_content
42
+ put(name, content) and !!reload(name)
43
+ end
44
+
45
+ def delete(name_or_regexp)
46
+ @file = nil
47
+
48
+ directory.files.reload
49
+
50
+ if name_or_regexp.class == Regexp
51
+ directory.files.select{|f| f.key.match(name_or_regexp)}.each do |file|
52
+ file.destroy
53
+ end
54
+ else
55
+ directory.files.get(name_or_regexp).destroy
56
+ end
57
+
58
+ true
59
+ end
60
+
61
+ def copy_to(klass, name)
62
+ klass.put(name, get(name))
63
+ end
64
+
65
+ def exists?(name)
66
+ !!file(name)
67
+ end
68
+
69
+ def modified(name)
70
+ file(name).last_modified + 0 if exists?(name)
71
+ end
72
+
73
+ def compress(name, content)
74
+ name = name.gsub(/(.+?)(\.gz)?$/, '\1.gz')
75
+ tmp = "/tmp/cabinet-tmp-#{name}-#{Time.now}"
76
+
77
+ File.open(tmp, 'w') do |f|
78
+ gz = Zlib::GzipWriter.new(f)
79
+ gz.write content
80
+ gz.close
81
+ end
82
+
83
+ put(name, File.read(tmp)) and (File.unlink(tmp) == 1)
84
+ end
85
+
86
+ def decompress(name)
87
+ Zlib::GzipReader.new(StringIO.new(get(name))).read
88
+ end
89
+
90
+ private
91
+ def file(name)
92
+ raise 'No directory specified' unless directory
93
+
94
+ if @file && @file.key == name
95
+ @file
96
+ else
97
+ reload(name)
98
+ end
99
+ end
100
+
101
+ def reload(name)
102
+ directory.files.reload
103
+ @file = directory.files.get(name)
104
+ end
105
+
106
+ def fog_provider(provider)
107
+ case provider.to_s.downcase
108
+ when 'aws', 's3', 'amazon'
109
+ 'AWS'
110
+ when 'rackspace', 'cloudfiles', 'cloud_files'
111
+ 'Rackspace'
112
+ when 'google', 'google_storage'
113
+ 'Google'
114
+ when 'local', 'localhost', 'filesystem'
115
+ 'Local'
116
+ else
117
+ raise ArgumentError, "#{provider} is not a valid provider"
118
+ end
119
+ end
120
+ end
121
+ end
@@ -1,3 +1,3 @@
1
1
  module Cabinet
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/cabinet.rb CHANGED
@@ -1,7 +1,19 @@
1
1
  require 'pathname'
2
+ require 'fog'
2
3
 
3
- module Cabinet; end
4
+ module Cabinet
5
+ def self.cloud(provider, options={})
6
+ self.init(provider, options)
7
+ end
8
+
9
+ def self.local(path='/')
10
+ self.init(:local, {:local_root => path})
11
+ end
12
+
13
+ def self.init(*args)
14
+ Cabinet::Instance.new(*args)
15
+ end
16
+ end
4
17
 
5
18
  dir = Pathname(__FILE__).dirname.expand_path
6
- require dir + 'cabinet/cloud'
7
- require dir + 'cabinet/local'
19
+ require dir + 'cabinet/instance'
@@ -0,0 +1,118 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe Cabinet::Instance do
4
+ before(:all) do
5
+ @local = Cabinet.local
6
+ @local.directory = '/tmp/cabinet_test'
7
+
8
+ @file_name = Forgery(:basic).text
9
+ @file_content = Forgery(:lorem_ipsum).text(:paragraphs, 10)
10
+ end
11
+
12
+ after(:all) do
13
+ @local.delete(/.*/)
14
+ end
15
+
16
+ it "creates files" do
17
+ @local.put(@file_name, @file_content).should == true
18
+ end
19
+
20
+ it "confirms that files exists" do
21
+ @local.exists?(@file_name).should == true
22
+ end
23
+
24
+ it "confirms that files don't exist" do
25
+ @local.exists?(@file_content).should == false
26
+ end
27
+
28
+ it "reads file content" do
29
+ @local.get(@file_name).should == @file_content
30
+ end
31
+
32
+ it "fetches last modified timestamp" do
33
+ @local.modified(@file_name).class.should == Time
34
+ end
35
+
36
+ it "appends files" do
37
+ extra_content = Forgery(:lorem_ipsum).text(:paragraph)
38
+ @local.append(@file_name, extra_content).should == true
39
+ @local.get(@file_name).should == @file_content + extra_content
40
+ end
41
+
42
+ it "list files with (and without) regular expressions" do
43
+ @local.list.should include(@file_name)
44
+ @local.list(/#{@file_name}/).should include(@file_name)
45
+ @local.list(/#{@file_content}/).should == []
46
+ end
47
+
48
+ it "creates an empty file using put with empty content argument" do
49
+ file = Forgery(:basic).text
50
+
51
+ @local.put(file, nil).should == true
52
+ @local.get(file).should == ""
53
+ end
54
+
55
+ it "creates an empty file using touch" do
56
+ file = Forgery(:basic).text
57
+
58
+ @local.touch(file).should == true
59
+ @local.get(file).should == ""
60
+ end
61
+
62
+ it "copies files from one cabinet instance to another" do
63
+ new_local = Cabinet.local
64
+ new_local.directory = "/tmp/cabinet_test_2"
65
+
66
+ @local.copy_to(new_local, @file_name).should == true
67
+ new_local.get(@file_name).should == @local.get(@file_name)
68
+
69
+ new_local.delete(@file_name)
70
+ end
71
+
72
+ it "updates last_modified timestamp using touch" do
73
+ original_time = @local.modified(@file_name)
74
+ original_content = @local.get(@file_name)
75
+
76
+ sleep(1) # to force time to pass update
77
+
78
+ @local.touch(@file_name).should == true
79
+ @local.modified(@file_name).should_not == original_time
80
+ @local.get(@file_name).should == original_content
81
+ end
82
+
83
+ it "compresses files using gzip" do
84
+ gz_file_name = @file_name + '.gz'
85
+
86
+ @local.compress(gz_file_name, @file_content).should == true
87
+ Zlib::GzipReader.new(StringIO.new(@local.get(gz_file_name))).read.should == @file_content
88
+ end
89
+
90
+ it "decompresses files using gzip" do
91
+ gz_file_name = @file_name + '.gz'
92
+ @local.decompress(gz_file_name).should == @file_content
93
+ end
94
+
95
+ it "deletes files" do
96
+ @local.delete(@file_name).should == true
97
+ @local.exists?(@file_name).should == false
98
+ end
99
+
100
+ it "bulk deletes files using regular expressions" do
101
+ (1..3).each {|n| @local.put("#{@file_name}.#{n}", @file_content)}
102
+ @local.delete(/#{@file_name}/)
103
+ (1..3).inject([]) {|arr, n| arr << @local.exists?("#{@file_name}.#{n}")}.should == [false, false, false]
104
+ end
105
+
106
+ it "tests cloud connection" do
107
+ credentials = YAML.load_file(File.expand_path(File.join(File.dirname(__FILE__), '..', 'cloud_credentials.yml')))
108
+ cloud = Cabinet.cloud(:rackspace, credentials)
109
+ cloud.container = 'cabinet_test'
110
+
111
+ cloud.put(@file_name, @file_content).should == true
112
+ cloud.list.should include(@file_name)
113
+ cloud.list(/#{@file_name}/).should include(@file_name)
114
+ cloud.get(@file_name).should == @file_content
115
+ cloud.delete(@file_name).should == true
116
+ cloud.list.should_not include(@file_name)
117
+ end
118
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,8 +2,4 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'cabinet')
2
2
  require 'forgery'
3
3
 
4
4
  RSpec.configure do |config|
5
- config.before(:suite) do
6
- @@file_name = 'cabinet.test'
7
- @@file_content = Forgery(:lorem_ipsum).text(:paragraphs, 10)
8
- end
9
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cabinet
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 3
10
- version: 0.1.3
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sebastian von Conrad
@@ -97,11 +97,9 @@ files:
97
97
  - Rakefile
98
98
  - cabinet.gemspec
99
99
  - lib/cabinet.rb
100
- - lib/cabinet/cloud.rb
101
- - lib/cabinet/local.rb
100
+ - lib/cabinet/instance.rb
102
101
  - lib/cabinet/version.rb
103
- - spec/cabinet/cloud_spec.rb
104
- - spec/cabinet/local_spec.rb
102
+ - spec/cabinet/instance_spec.rb
105
103
  - spec/cloud_credentials.yml
106
104
  - spec/spec_helper.rb
107
105
  has_rdoc: true
@@ -139,7 +137,6 @@ signing_key:
139
137
  specification_version: 3
140
138
  summary: ""
141
139
  test_files:
142
- - spec/cabinet/cloud_spec.rb
143
- - spec/cabinet/local_spec.rb
140
+ - spec/cabinet/instance_spec.rb
144
141
  - spec/cloud_credentials.yml
145
142
  - spec/spec_helper.rb
data/lib/cabinet/cloud.rb DELETED
@@ -1,99 +0,0 @@
1
- require 'fog'
2
-
3
- module Cabinet
4
- class Cloud
5
- attr_accessor :connection, :container
6
-
7
- def initialize(config)
8
- root_dir = config.delete(:container)
9
- self.connection = Fog::Rackspace::Storage.new(config)
10
- self.container = connection.directories.get(root_dir) || connection.directories.create(:key => root_dir)
11
- end
12
-
13
- def get(name)
14
- file(name).body
15
- end
16
-
17
- def list(regexp=/.*/)
18
- container.files.reload
19
- container.files.select{|f| f.key.match(regexp)}.to_a.map(&:key)
20
- end
21
-
22
- def put(name, content)
23
- begin
24
- container.files.create(:key => name, :body => content).content_length == content.length
25
- rescue
26
- false
27
- end
28
- end
29
-
30
- def append(name, new_content)
31
- content = exists?(name) ? get(name) + new_content : new_content
32
- put(name, content) and !!reload(name)
33
- end
34
-
35
- def delete(name_or_regexp)
36
- @file = nil
37
-
38
- container.files.reload
39
-
40
- if name_or_regexp.class == Regexp
41
- container.files.select{|f| f.key.match(name_or_regexp)}.each do |file|
42
- file.destroy
43
- end
44
- else
45
- container.files.get(name_or_regexp).destroy
46
- end
47
-
48
- true
49
- end
50
-
51
- def copy_to(klass_or_sym, name)
52
- if klass_or_sym.is_a? Symbol
53
- c = case klass_or_sym
54
- when :local
55
- Local.new('/tmp')
56
- end
57
- else
58
- c = klass_or_sym
59
- end
60
-
61
- c.put(name, get(name))
62
- end
63
-
64
- def exists?(name)
65
- !!file(name)
66
- end
67
-
68
- def modified(name)
69
- file(name).last_modified + 0 if exists?(name)
70
- end
71
-
72
- def gzip(name, content)
73
- name = name.gsub(/(.+?)(\.gz)?$/, '\1.gz')
74
- local = "/tmp/#{name}"
75
-
76
- File.open(local, 'w') do |f|
77
- gz = Zlib::GzipWriter.new(f)
78
- gz.write content
79
- gz.close
80
- end
81
-
82
- put(name, File.read(local)) and File.unlink(local)
83
- end
84
-
85
- private
86
- def file(name)
87
- if @file && @file.key == name
88
- @file
89
- else
90
- reload(name)
91
- end
92
- end
93
-
94
- def reload(name)
95
- container.files.reload
96
- @file = container.files.get(name)
97
- end
98
- end
99
- end
data/lib/cabinet/local.rb DELETED
@@ -1,42 +0,0 @@
1
- module Cabinet
2
- class Local
3
- attr_accessor :dir
4
-
5
- def initialize(root_dir)
6
- self.dir = root_dir.chomp('/') + '/'
7
- end
8
-
9
- def get(file)
10
- raise ArgumentError, "The file #{file} does not exist" unless exists?(file)
11
- File.read(dir + file)
12
- end
13
-
14
- def put(file, content)
15
- File.open(dir + file, 'wb') {|f| f.write(content)} == content.length
16
- end
17
-
18
- def append(file, content)
19
- File.open(dir + file, 'ab') {|f| f.write(content)} == content.length
20
- end
21
-
22
- def delete(file_or_regexp)
23
- File.delete *Dir.glob(dir + file_or_regexp)
24
- end
25
-
26
- def exists?(file)
27
- File.exists?(dir + file)
28
- end
29
-
30
- def modified(file)
31
- File.mtime(dir + file) if exists?(file)
32
- end
33
-
34
- def gzip(file, content)
35
- File.open(dir + file, 'w') do |f|
36
- gz = Zlib::GzipWriter.new(f)
37
- gz.write content
38
- gz.close
39
- end
40
- end
41
- end
42
- end
@@ -1,84 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
-
3
- describe Cabinet::Cloud do
4
- before(:all) do
5
- credentials = YAML.load_file(File.expand_path(File.join(File.dirname(__FILE__), '..', 'cloud_credentials.yml')))
6
- @cc = Cabinet::Cloud.new({:container => 'cabinet_test'}.merge(credentials))
7
- end
8
-
9
- it "should create file" do
10
- @cc.put(@@file_name, @@file_content).should == true
11
- end
12
-
13
- it "should confirm file exists" do
14
- @cc.exists?(@@file_name).should == true
15
- end
16
-
17
- it "should confirm file does not exist" do
18
- @cc.exists?(@@file_content).should == false
19
- end
20
-
21
- it "should read file" do
22
- @cc.get(@@file_name).should == @@file_content
23
- end
24
-
25
- it "should get last modified" do
26
- @cc.modified(@@file_name).class.should == Time
27
- end
28
-
29
- it "should append file" do
30
- extra_content = Forgery(:lorem_ipsum).text(:paragraph)
31
- @cc.append(@@file_name, extra_content).should == true
32
- @cc.get(@@file_name).should == @@file_content + extra_content
33
- end
34
-
35
- it "should list files" do
36
- @cc.list.should include(@@file_name)
37
- @cc.list(/#{@@file_name}/).should include(@@file_name)
38
- @cc.list(/#{@@file_content}/).should == []
39
- end
40
-
41
- it "should copy file to local filesystem using object" do
42
- cl = Cabinet::Local.new('/tmp')
43
- cl.delete(@@file_name) if cl.exists?(@@file_name)
44
-
45
- @cc.copy_to(cl, @@file_name)
46
- cl.exists?(@@file_name).should == true
47
- cl.delete(@@file_name)
48
- end
49
-
50
- it "should copy file to local filesystem using symbol" do
51
- File.unlink("/tmp/#{@@file_name}") if File.exists?("/tmp/#{@@file_name}")
52
- @cc.copy_to(:local, @@file_name)
53
- File.exists?("/tmp/#{@@file_name}").should == true
54
- File.unlink("/tmp/#{@@file_name}")
55
- end
56
-
57
- it "should not overwrite file"
58
-
59
- it "should overwrite file if :force => true"
60
-
61
- it "should gzip file" do
62
- gz_file_name = @@file_name + '.gz'
63
- File.unlink("/tmp/#{gz_file_name}") if File.exists?("/tmp/#{gz_file_name}")
64
-
65
- @cc.gzip(gz_file_name, @@file_content)
66
- @cc.copy_to(:local, gz_file_name)
67
-
68
- Zlib::GzipReader.open("/tmp/#{gz_file_name}") {|gz| gz.read}.should == @@file_content
69
-
70
- @cc.delete(gz_file_name)
71
- File.unlink("/tmp/#{gz_file_name}")
72
- end
73
-
74
- it "should delete file" do
75
- @cc.delete(@@file_name)
76
- @cc.exists?(@@file_name).should == false
77
- end
78
-
79
- it "should bulk delete files" do
80
- (1..3).each {|n| @cc.put("#{@@file_name}.#{n}", @@file_content)}
81
- @cc.delete(/#{@@file_name}/)
82
- (1..3).inject([]) {|arr, n| arr << @cc.exists?("#{@@file_name}.#{n}")}.should == [false, false, false]
83
- end
84
- end
@@ -1,57 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
-
3
- describe Cabinet::Local do
4
- before(:all) do
5
- @cl = Cabinet::Local.new('/tmp')
6
- end
7
-
8
- it "should create file" do
9
- @cl.put(@@file_name, @@file_content).should == true
10
- end
11
-
12
- it "should confirm file exists" do
13
- @cl.exists?(@@file_name).should == true
14
- end
15
-
16
- it "should confirm file does not exist" do
17
- @cl.exists?(@@file_content).should == false
18
- end
19
-
20
- it "should read file" do
21
- @cl.get(@@file_name).should == @@file_content
22
- end
23
-
24
- it "should see last modified" do
25
- @cl.modified(@@file_name).class.should == Time
26
- end
27
-
28
- it "should append file" do
29
- extra_content = Forgery(:lorem_ipsum).text(:paragraph)
30
- @cl.append(@@file_name, extra_content).should == true
31
- @cl.get(@@file_name).should == @@file_content + extra_content
32
- end
33
-
34
- it "should list files"
35
-
36
- it "should not overwrite file"
37
-
38
- it "should overwrite file if :force => true"
39
-
40
- it "should gzip file" do
41
- gz_file_name = @@file_name + '.gz'
42
- @cl.gzip(gz_file_name, @@file_content)
43
- Zlib::GzipReader.open("/tmp/#{gz_file_name}") {|gz| gz.read}.should == @@file_content
44
- @cl.delete(gz_file_name)
45
- end
46
-
47
- it "should delete file" do
48
- @cl.delete(@@file_name)
49
- @cl.exists?(@@file_name).should == false
50
- end
51
-
52
- it "should bulk delete files" do
53
- (1..3).each {|n| @cl.put("#{@@file_name}.#{n}", @@file_content)}
54
- @cl.delete("#{@@file_name}*")
55
- (1..3).inject([]) {|arr, n| arr << @cl.exists?("#{@@file_name}.#{n}")}.should == [false, false, false]
56
- end
57
- end