vfs 0.3.15 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,26 +1,25 @@
1
1
  module Vfs
2
2
  class Entry
3
- attr_reader :storage, :path, :path_cache
3
+ attr_reader :driver, :path, :path_cache
4
4
 
5
5
  def initialize *args
6
6
  if args.size == 1 and args.first.is_a? Entry
7
7
  entry = args.first
8
8
  @path_cache = entry.path_cache
9
- @storage, @path = entry.storage, entry.path
9
+ @driver, @path = entry.driver, entry.path
10
10
  else
11
- storage, path = *args
11
+ driver, path = *args
12
12
  @path_cache = Path.new path
13
- @storage, @path = storage, path_cache.to_s
13
+ @driver, @path = driver, path_cache.to_s
14
14
  end
15
- raise "storage not defined!" unless self.storage
15
+ raise "driver not defined!" unless self.driver
16
16
  end
17
17
 
18
-
19
18
  #
20
19
  # Navigation
21
20
  #
22
21
  def parent
23
- Dir.new(storage, path_cache + '..')
22
+ Dir.new(driver, path_cache + '..')
24
23
  end
25
24
 
26
25
 
@@ -30,7 +29,7 @@ module Vfs
30
29
  def dir path = nil
31
30
  if path
32
31
  new_path = path_cache + path
33
- Dir.new storage, new_path
32
+ Dir.new driver, new_path
34
33
  else
35
34
  Dir.new self
36
35
  end
@@ -40,7 +39,7 @@ module Vfs
40
39
  def file path = nil
41
40
  if path
42
41
  new_path = path_cache + path
43
- File.new storage, new_path
42
+ File.new driver, new_path
44
43
  else
45
44
  File.new self
46
45
  end
@@ -49,10 +48,9 @@ module Vfs
49
48
 
50
49
  def entry path = nil
51
50
  entry = if path
52
-
53
51
  new_path = path_cache + path
54
52
  klass = new_path.probably_dir? ? Dir : UniversalEntry
55
- entry = klass.new storage, new_path
53
+ klass.new driver, new_path
56
54
  else
57
55
  UniversalEntry.new self
58
56
  end
@@ -65,7 +63,7 @@ module Vfs
65
63
  # Attributes
66
64
  #
67
65
  def get attr_name = nil
68
- attrs = storage.open{|fs| fs.attributes(path)}
66
+ attrs = driver.open{driver.attributes(path)}
69
67
  (attr_name and attrs) ? attrs[attr_name] : attrs
70
68
  end
71
69
 
@@ -88,19 +86,19 @@ module Vfs
88
86
  end
89
87
 
90
88
  def tmp &block
91
- storage.open do |fs|
89
+ driver.open do
92
90
  if block
93
- fs.tmp do |path|
94
- block.call Dir.new(storage, path)
91
+ driver.tmp do |path|
92
+ block.call Dir.new(driver, path)
95
93
  end
96
94
  else
97
- Dir.new storage, fs.tmp
95
+ Dir.new driver, driver.tmp
98
96
  end
99
97
  end
100
98
  end
101
99
 
102
100
  def local?
103
- storage.local?
101
+ driver.local?
104
102
  end
105
103
 
106
104
 
@@ -108,22 +106,42 @@ module Vfs
108
106
  # Utils
109
107
  #
110
108
  def inspect
111
- "#{storage}#{':' unless storage.to_s.empty?}#{path}"
109
+ "#{driver}#{':' unless driver.to_s.empty?}#{path}"
112
110
  end
113
111
  alias_method :to_s, :inspect
114
112
 
115
113
  def == other
116
114
  return false unless other.is_a? Entry
117
- storage == other.storage and path == other.path
115
+ driver == other.driver and path == other.path
118
116
  end
119
117
 
120
118
  def hash
121
- storage.hash + path.hash
119
+ driver.hash + path.hash
122
120
  end
123
121
 
124
122
  def eql? other
125
123
  return false unless other.class == self.class
126
- storage.eql?(other.storage) and path.eql?(other.path)
124
+ driver.eql?(other.driver) and path.eql?(other.path)
127
125
  end
126
+
127
+ protected
128
+ def destroy_entry first = :file, second = :dir
129
+ driver.open do
130
+ begin
131
+ driver.send :"delete_#{first}", path
132
+ rescue StandardError => e
133
+ attrs = get
134
+ if attrs and attrs[first]
135
+ # some unknown error
136
+ raise e
137
+ elsif attrs and attrs[second]
138
+ driver.send :"delete_#{second}", path
139
+ else
140
+ # do nothing, entry already not exist
141
+ end
142
+ end
143
+ end
144
+ self
145
+ end
128
146
  end
129
147
  end
@@ -11,13 +11,13 @@ module Vfs
11
11
  #
12
12
  def read options = {}, &block
13
13
  options[:bang] = true unless options.include? :bang
14
- storage.open do |fs|
14
+ driver.open do
15
15
  begin
16
16
  if block
17
- fs.read_file path, &block
17
+ driver.read_file path, &block
18
18
  else
19
19
  data = ""
20
- fs.read_file(path){|buff| data << buff}
20
+ driver.read_file(path){|buff| data << buff}
21
21
  data
22
22
  end
23
23
  rescue StandardError => e
@@ -39,18 +39,14 @@ module Vfs
39
39
  end
40
40
  end
41
41
 
42
- def content options = {}
43
- read options
44
- end
42
+ # def content options = {}
43
+ # read options
44
+ # end
45
45
 
46
46
  def create options = {}
47
47
  write '', options
48
48
  self
49
49
  end
50
- def create! options = {}
51
- options[:override] = true
52
- create options
53
- end
54
50
 
55
51
  def write *args, &block
56
52
  if block
@@ -61,35 +57,24 @@ module Vfs
61
57
  end
62
58
  raise "can't do :override and :append at the same time!" if options[:override] and options[:append]
63
59
 
64
- storage.open do |fs|
65
- # TODO2 Performance lost, extra call to check file existence
66
- # We need to check if the file exist before writing to it, otherwise it's
67
- # impossible to distinguish if the StandardError caused by the 'already exist' error or
68
- # some other error.
69
- entry = self.entry
70
- if entry.exist?
71
- if options[:override]
72
- entry.destroy
73
- else
74
- raise Error, "entry #{self} already exist!"
75
- end
76
- end
77
-
60
+ driver.open do
78
61
  try = 0
79
62
  begin
80
63
  try += 1
81
64
  if block
82
- fs.write_file(path, options[:append], &block)
65
+ driver.write_file(path, options[:append], &block)
83
66
  else
84
- fs.write_file(path, options[:append]){|writer| writer.write data}
67
+ driver.write_file(path, options[:append]){|writer| writer.write data}
85
68
  end
86
69
  rescue StandardError => error
87
70
  parent = self.parent
88
- if parent.exist?
89
- # some unknown error
90
- raise error
91
- else
71
+ if entry.exist?
72
+ entry.destroy
73
+ elsif !parent.exist?
92
74
  parent.create(options)
75
+ else
76
+ # unknown error
77
+ raise error
93
78
  end
94
79
 
95
80
  try < 2 ? retry : raise(error)
@@ -97,11 +82,6 @@ module Vfs
97
82
  end
98
83
  self
99
84
  end
100
- def write! *args, &block
101
- args << {} unless args.last.is_a? Hash
102
- args.last[:override] = true
103
- write *args, &block
104
- end
105
85
 
106
86
  def append *args, &block
107
87
  options = (args.last.is_a?(Hash) && args.pop) || {}
@@ -110,37 +90,12 @@ module Vfs
110
90
  end
111
91
 
112
92
  def update options = {}, &block
113
- options[:override] = true
114
93
  data = read options
115
94
  write block.call(data), options
116
95
  end
117
96
 
118
- def destroy options = {}
119
- storage.open do |fs|
120
- begin
121
- fs.delete_file path
122
- self
123
- rescue StandardError => e
124
- attrs = get
125
- if attrs and attrs[:dir]
126
- if options[:force]
127
- dir.destroy
128
- else
129
- raise Error, "can't destroy Dir #{dir} (you are trying to destroy it as if it's a File)"
130
- end
131
- elsif attrs and attrs[:file]
132
- # unknown internal error
133
- raise e
134
- else
135
- # do nothing, file already not exist
136
- end
137
- end
138
- end
139
- self
140
- end
141
- def destroy! options = {}
142
- options[:force] = true
143
- destroy options
97
+ def destroy
98
+ destroy_entry
144
99
  end
145
100
 
146
101
 
@@ -166,20 +121,12 @@ module Vfs
166
121
 
167
122
  target
168
123
  end
169
- def copy_to! to, options = {}
170
- options[:override] = true
171
- copy_to to, options
172
- end
173
124
 
174
- def move_to to, options = {}
175
- copy_to to, options
176
- destroy options
125
+ def move_to to
126
+ copy_to to
127
+ destroy
177
128
  to
178
129
  end
179
- def move_to! to, options = {}
180
- options[:override] = true
181
- move_to to, options
182
- end
183
130
 
184
131
 
185
132
  #
@@ -8,17 +8,17 @@ module Vfs
8
8
  end
9
9
 
10
10
 
11
+ def copy_to to, options = {}
12
+ from = file? ? to_file : to_dir
13
+ from.copy_to to, options
14
+ end
15
+
16
+
11
17
  #
12
18
  # CRUD
13
19
  #
14
- def destroy options = {}
15
- storage.open do |fs|
16
- attrs = get
17
- fs.delete_dir path if attrs and attrs[:dir]
18
- fs.delete_file path if attrs and attrs[:file]
19
- end
20
- self
20
+ def destroy
21
+ destroy_entry
21
22
  end
22
- alias_method :destroy!, :destroy
23
23
  end
24
24
  end
@@ -0,0 +1,30 @@
1
+ class String
2
+ def to_entry_on driver = nil
3
+ path = self
4
+ driver ||= Vfs.default_driver
5
+
6
+ path = "./#{path}" unless path =~ /^[\/\.\~]/
7
+ Vfs::Entry.new(driver, path).entry
8
+ end
9
+ alias_method :to_entry, :to_entry_on
10
+
11
+ def to_file_on driver = nil
12
+ to_entry_on(driver).file
13
+ end
14
+ alias_method :to_file, :to_file_on
15
+
16
+ def to_dir_on driver = nil
17
+ to_entry_on(driver).dir
18
+ end
19
+ alias_method :to_dir, :to_dir_on
20
+ end
21
+
22
+ class File
23
+ def to_entry
24
+ path.to_entry
25
+ end
26
+
27
+ def to_file
28
+ path.to_file
29
+ end
30
+ end
data/lib/vfs/vfs.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Vfs
2
2
  class << self
3
- def default_storage
4
- ::Vfs::Storages::Local.new
3
+ def default_driver
4
+ ::Vfs::Drivers::Local.new
5
5
  end
6
6
 
7
7
  def to_entry
data/readme.md CHANGED
@@ -51,7 +51,7 @@ projects['cool_app'].copy_to deploy_dir
51
51
 
52
52
  dbc = deploy_dir.file('config/database.yml') # <= the 'config' dir not exist yet
53
53
  dbc.write("user: root\npassword: secret") # <= now the 'database.yml' and parent 'config' has been created
54
- dbc.content =~ /database/ # => false, we forgot to add the database
54
+ dbc.read =~ /database/ # => false, we forgot to add the database
55
55
  dbc.append("\ndatabase: mysql") # let's do it
56
56
 
57
57
  dbc.update do |content| # and add host info
@@ -1,29 +1,30 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Container' do
4
- with_test_fs
4
+ with_test_dir
5
5
 
6
6
  it "should threat paths as UniversalEntry except it ends with '/'" do
7
- test_fs.should_receive(:entry).with('tmp/a/b')
8
- test_fs['tmp/a/b']
7
+ test_dir.should_receive(:entry).with('tmp/a/b')
8
+ test_dir['tmp/a/b']
9
9
 
10
- test_fs.should_receive(:dir).with('tmp/a/b')
11
- test_fs['tmp/a/b/']
10
+ test_dir.should_receive(:dir).with('tmp/a/b')
11
+ test_dir['tmp/a/b/']
12
12
  end
13
13
 
14
14
  it '/' do
15
- test_fs[:some_path].should == test_fs / :some_path
16
- test_fs[:some_path][:another_path].should == test_fs / :some_path / :another_path
15
+ test_dir[:some_path].should == test_dir / :some_path
16
+ test_dir[:some_path][:another_path].should == test_dir / :some_path / :another_path
17
17
  end
18
18
 
19
19
  it "UniversalEntry should be wrapped inside of proxy, Dir and File should not" do
20
- -> {test_fs.dir.proxy?}.should raise_error(NoMethodError)
21
- -> {test_fs.file.proxy?}.should raise_error(NoMethodError)
22
- test_fs.entry.proxy?.should be_true
20
+ -> {test_dir.dir.proxy?}.should raise_error(NoMethodError)
21
+ -> {test_dir.file.proxy?}.should raise_error(NoMethodError)
22
+ test_dir.entry.proxy?.should be_true
23
23
  end
24
24
 
25
25
  it "sometimes it also should inexplicitly guess that path is a Dir instead of UniversalEntry (but still wrap it inside of Proxy)" do
26
- dir = test_fs['tmp/a/..']
26
+
27
+ dir = test_dir['tmp/a/..']
27
28
  dir.proxy?.should be_true
28
29
  dir.should be_a(Vfs::Dir)
29
30
  end
data/spec/dir_spec.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Dir' do
4
- with_test_fs
4
+ with_test_dir
5
5
 
6
6
  before do
7
- @path = test_fs['a/b/c']
7
+ @path = test_dir['a/b/c']
8
8
  end
9
9
 
10
10
  describe 'existence' do
@@ -13,7 +13,7 @@ describe 'Dir' do
13
13
  @path.file.create
14
14
  @path.should be_file
15
15
  @path.dir.should_not exist
16
- @path.dir.create!
16
+ @path.dir.create
17
17
  @path.should be_dir
18
18
  @path.dir.should exist
19
19
  end
@@ -27,7 +27,6 @@ describe 'Dir' do
27
27
  describe 'create' do
28
28
  it 'should be chainable' do
29
29
  @path.dir.create.should == @path
30
- @path.dir.create!.should == @path
31
30
  end
32
31
 
33
32
  it 'should create parent dirs if not exists' do
@@ -41,27 +40,29 @@ describe 'Dir' do
41
40
  @path.dir.create
42
41
  end
43
42
 
44
- it 'should override existing file if override specified' do
43
+ it 'should override existing file' do
45
44
  @path.file.create
46
45
  @path.should be_file
47
- -> {@path.dir.create}.should raise_error(Vfs::Error, /exist/)
48
- @path.dir.create!
46
+ @path.dir.create
49
47
  @path.should be_dir
50
48
  end
51
49
 
52
- it 'should override existing dir if override specified' do
53
- @path.dir.create
54
- @path.should be_dir
55
- @path.dir.create!
56
- @path.should be_dir
50
+ it 'should not override existing dir with content' do
51
+ dir = @path.dir
52
+ dir.create
53
+ file = dir.file :file
54
+ file.create
55
+ file.should exist
56
+
57
+ dir.create
58
+ file.should exist
57
59
  end
58
60
  end
59
61
 
60
62
  describe 'destroying' do
61
- it "should raise error if it's trying to destroy a file (unless force specified)" do
63
+ it "should destroy a file" do
62
64
  @path.file.create
63
- -> {@path.dir.destroy}.should raise_error(Vfs::Error, /can't destroy File/)
64
- @path.dir.destroy!
65
+ @path.dir.destroy
65
66
  @path.entry.should_not exist
66
67
  end
67
68
 
@@ -72,9 +73,9 @@ describe 'Dir' do
72
73
  it 'should destroy recursivelly' do
73
74
  dir = @path.dir
74
75
  dir.create
75
- dir.file('file').write 'something'
76
- dir.dir('dir').create.tap do |dir|
77
- dir.file('file2').write 'something2'
76
+ dir.file(:file).write 'something'
77
+ dir.dir(:dir).create.tap do |dir|
78
+ dir.file(:file2).write 'something2'
78
79
  end
79
80
 
80
81
  dir.destroy
@@ -83,7 +84,6 @@ describe 'Dir' do
83
84
 
84
85
  it 'should be chainable' do
85
86
  @path.dir.destroy.should == @path
86
- @path.dir.destroy!.should == @path
87
87
  end
88
88
  end
89
89
 
@@ -97,10 +97,14 @@ describe 'Dir' do
97
97
  it 'entries' do
98
98
  -> {@path['non_existing'].entries}.should raise_error(Vfs::Error, /not exist/)
99
99
  @path['non_existing'].entries(bang: false).should == []
100
- @path.entries.to_set.should be_eql([@path.dir('dir'), @path.file('file')].to_set)
100
+ @path.entries.to_set.should be_eql([@path.entry('dir'), @path.entry('file')].to_set)
101
101
  list = []
102
102
  @path.entries{|e| list << e}
103
- list.to_set.should be_eql([@path.dir('dir'), @path.file('file')].to_set)
103
+ list.to_set.should be_eql([@path.entry('dir'), @path.entry('file')].to_set)
104
+ end
105
+
106
+ it 'entries with type' do
107
+ @path.entries(type: true).to_set.should be_eql([@path.dir('dir'), @path.file('file')].to_set)
104
108
  end
105
109
 
106
110
  it "glob search support" do
@@ -151,32 +155,28 @@ describe 'Dir' do
151
155
  end
152
156
 
153
157
  shared_examples_for 'copy_to behavior' do
154
- it 'should not copy to file (and overwrite if forced)' do
155
- -> {@from.copy_to @to.file}.should raise_error(/can't copy Dir to File/)
156
-
157
- @from.copy_to! @to.file
158
+ it 'should copy to file and overwrite it' do
159
+ @from.copy_to @to.file
158
160
  @to['file'].read.should == 'something'
159
161
  end
160
162
 
161
- it 'should not override files (and override if forced)' do
163
+ it 'should override files' do
162
164
  @from.copy_to @to
163
- -> {@from.copy_to @to}.should raise_error(/already exist/)
164
165
 
165
- @from['dir/file2'].write! 'another'
166
- @from.copy_to! @to
166
+ @from['dir/file2'].write 'another'
167
+ @from.copy_to @to
167
168
  @to['dir/file2'].read.should == 'another'
168
169
  end
169
170
 
170
- it 'should copy to UniversalEntry (and overwrite if forced)' do
171
+ it 'should copy to UniversalEntry (and overwrite)' do
171
172
  @from.copy_to @to.entry
172
- -> {@from.copy_to @to.entry}.should raise_error(/already exist/)
173
173
 
174
- @from.copy_to! @to.entry
174
+ @from.copy_to @to.entry
175
175
  @to['file'].read.should == 'something'
176
176
  end
177
177
 
178
178
  it "shouldn't delete existing content of directory" do
179
- @to.dir.create!
179
+ @to.dir.create
180
180
  @to.file('existing_file').write 'existing_content'
181
181
  @to.dir('existing_dir').create
182
182
  @to.file('dir/existing_file2').write 'existing_content2'
@@ -193,16 +193,21 @@ describe 'Dir' do
193
193
 
194
194
  it 'should be chainable' do
195
195
  @from.copy_to(@to).should == @to
196
- @from.copy_to!(@to).should == @to
197
196
  end
198
197
 
199
198
  it "should override without deleting other files" do
200
199
  @from.copy_to(@to).should == @to
201
200
  @to.file('other_file').write 'other'
202
201
 
203
- @from.copy_to!(@to).should == @to
202
+ @from.copy_to(@to).should == @to
204
203
  @to.file('other_file').read.should == 'other'
205
204
  end
205
+
206
+ it "should raise error if try to copy file as dir" do
207
+ dir = @from.dir 'file'
208
+ dir.file?.should be_true
209
+ -> {dir.copy_to @to}.should raise_error(Vfs::Error)
210
+ end
206
211
  end
207
212
 
208
213
  describe 'general copy' do
@@ -212,7 +217,7 @@ describe 'Dir' do
212
217
  # prevenging usage of :efficient_dir_copy
213
218
  # Vfs::Dir.dont_use_efficient_dir_copy = true
214
219
 
215
- @to = test_fs['to']
220
+ @to = test_dir['to']
216
221
  end
217
222
  # after do
218
223
  # Vfs::Dir.dont_use_efficient_dir_copy = false
@@ -223,7 +228,7 @@ describe 'Dir' do
223
228
  # it_should_behave_like 'copy_to behavior'
224
229
  #
225
230
  # before do
226
- # @to = test_fs['to']
231
+ # @to = test_dir['to']
227
232
  # end
228
233
  # end
229
234
  end
@@ -231,19 +236,14 @@ describe 'Dir' do
231
236
  describe 'moving' do
232
237
  it 'move_to' do
233
238
  from, to = @path.file('from'), @path.file('to')
234
- from.should_receive(:copy_to).with(to, {})
235
- from.should_receive(:destroy).with({})
239
+ from.should_receive(:copy_to).with(to)
240
+ from.should_receive(:destroy).with()
236
241
  from.move_to to
237
-
238
- from.should_receive(:move_to).with(to, override: true)
239
- from.move_to! to
240
242
  end
241
243
 
242
244
  it 'should be chainable' do
243
245
  from, to = @path.dir('from').create, @path.dir('to')
244
246
  from.move_to(to).should == to
245
- from.create
246
- from.move_to!(to).should == to
247
247
  end
248
248
  end
249
249
  end