vfs 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/vfs.rb +3 -0
- data/lib/vfs/entries/dir.rb +66 -76
- data/lib/vfs/entries/entry.rb +8 -7
- data/lib/vfs/entries/entry/special_attributes.rb +26 -0
- data/lib/vfs/entries/file.rb +1 -1
- data/lib/vfs/storages/hash_fs.rb +32 -12
- data/lib/vfs/storages/local.rb +8 -2
- data/lib/vfs/storages/specification.rb +4 -2
- data/lib/vfs/vfs.rb +34 -0
- data/readme.md +52 -43
- data/spec/dir_spec.rb +60 -46
- data/spec/entry_spec.rb +10 -0
- data/spec/storages/local_spec.rb +6 -0
- metadata +6 -12
data/Rakefile
CHANGED
data/lib/vfs.rb
CHANGED
data/lib/vfs/entries/dir.rb
CHANGED
@@ -97,7 +97,7 @@ module Vfs
|
|
97
97
|
storage.open_fs do |fs|
|
98
98
|
begin
|
99
99
|
list = []
|
100
|
-
fs.
|
100
|
+
fs.each_entry path do |name, type|
|
101
101
|
next if options[:filter] and options[:filter] != type
|
102
102
|
entry = if type == :dir
|
103
103
|
dir(name)
|
@@ -140,6 +140,10 @@ module Vfs
|
|
140
140
|
end
|
141
141
|
alias_method :has?, :include?
|
142
142
|
|
143
|
+
def empty?
|
144
|
+
entries.empty?
|
145
|
+
end
|
146
|
+
|
143
147
|
|
144
148
|
#
|
145
149
|
# Transfers
|
@@ -162,53 +166,7 @@ module Vfs
|
|
162
166
|
raise "can't copy to unknown Entry!"
|
163
167
|
end
|
164
168
|
|
165
|
-
|
166
|
-
try = 0
|
167
|
-
begin
|
168
|
-
try += 1
|
169
|
-
self.class.efficient_dir_copy(self, target) || self.class.unefficient_dir_copy(self, target)
|
170
|
-
rescue StandardError => error
|
171
|
-
unknown_errors = 0
|
172
|
-
|
173
|
-
attrs = get
|
174
|
-
if attrs[:file]
|
175
|
-
raise Error, "can't copy File as a Dir ('#{self}')!"
|
176
|
-
elsif attrs[:dir]
|
177
|
-
# some unknown error (but it also maybe caused by to be fixed error in 'target')
|
178
|
-
unknown_errors += 1
|
179
|
-
else
|
180
|
-
raise Error, "'#{self}' not exist!" if options[:bang]
|
181
|
-
return target
|
182
|
-
end
|
183
|
-
|
184
|
-
attrs = target.get
|
185
|
-
if attrs[:file]
|
186
|
-
if options[:override]
|
187
|
-
to.destroy
|
188
|
-
else
|
189
|
-
raise Vfs::Error, "entry #{target} already exist!"
|
190
|
-
end
|
191
|
-
elsif attrs[:dir]
|
192
|
-
if options[:override]
|
193
|
-
to.destroy
|
194
|
-
else
|
195
|
-
raise Vfs::Error, "entry #{target} already exist!"
|
196
|
-
end
|
197
|
-
else
|
198
|
-
parent = to.parent
|
199
|
-
if parent.exist?
|
200
|
-
# some unknown error (but it also maybe caused by already fixed error in 'from')
|
201
|
-
unknown_errors += 1
|
202
|
-
else
|
203
|
-
parent.create(options)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
raise error if unknown_errors > 1
|
208
|
-
|
209
|
-
retry if try < 2
|
210
|
-
end
|
211
|
-
end
|
169
|
+
efficient_dir_copy(target, options) || unefficient_dir_copy(target, options)
|
212
170
|
|
213
171
|
target
|
214
172
|
end
|
@@ -228,44 +186,76 @@ module Vfs
|
|
228
186
|
end
|
229
187
|
|
230
188
|
protected
|
231
|
-
def
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
189
|
+
def unefficient_dir_copy to, options
|
190
|
+
to.create options
|
191
|
+
entries options do |e|
|
192
|
+
if e.is_a? Dir
|
193
|
+
e.copy_to to.dir(e.name), options
|
194
|
+
elsif e.is_a? File
|
195
|
+
e.copy_to to.file(e.name), options
|
196
|
+
else
|
197
|
+
raise 'internal error'
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def efficient_dir_copy to, options
|
203
|
+
storage.open_fs do |fs|
|
204
|
+
try = 0
|
205
|
+
begin
|
206
|
+
try += 1
|
207
|
+
self.class.efficient_dir_copy(self, to, options[:override])
|
208
|
+
rescue StandardError => error
|
209
|
+
unknown_errors = 0
|
210
|
+
|
211
|
+
attrs = get
|
212
|
+
if attrs[:file]
|
213
|
+
raise Error, "can't copy File as a Dir ('#{self}')!"
|
214
|
+
elsif attrs[:dir]
|
215
|
+
# some unknown error (but it also maybe caused by to be fixed error in 'to')
|
216
|
+
unknown_errors += 1
|
217
|
+
else
|
218
|
+
raise Error, "'#{self}' not exist!" if options[:bang]
|
219
|
+
return true
|
220
|
+
end
|
221
|
+
|
222
|
+
attrs = to.get
|
223
|
+
if attrs[:file]
|
224
|
+
if options[:override]
|
225
|
+
to.destroy
|
244
226
|
else
|
245
|
-
raise
|
227
|
+
raise Vfs::Error, "entry #{to} already exist!"
|
246
228
|
end
|
229
|
+
elsif attrs[:dir]
|
230
|
+
unknown_errors += 1
|
231
|
+
# if options[:override]
|
232
|
+
# to.destroy
|
233
|
+
# else
|
234
|
+
# dir_already_exist = true
|
235
|
+
# # raise Vfs::Error, "entry #{to} already exist!"
|
236
|
+
# end
|
237
|
+
else # parent not exist
|
238
|
+
parent = to.parent
|
239
|
+
if parent.exist?
|
240
|
+
# some unknown error (but it also maybe caused by already fixed error in 'from')
|
241
|
+
unknown_errors += 1
|
242
|
+
else
|
243
|
+
parent.create(options)
|
244
|
+
end
|
247
245
|
end
|
246
|
+
|
247
|
+
raise error if unknown_errors > 1
|
248
|
+
try < 2 ? retry : raise(error)
|
248
249
|
end
|
249
250
|
end
|
250
|
-
|
251
|
-
# target.create options
|
252
|
-
# entries do |e|
|
253
|
-
# if e.is_a? Dir
|
254
|
-
# e.copy_to target.dir(e.name), options
|
255
|
-
# elsif e.is_a? File
|
256
|
-
# e.copy_to target.file(e.name), options
|
257
|
-
# else
|
258
|
-
# raise 'internal error'
|
259
|
-
# end
|
260
|
-
# end
|
261
251
|
end
|
262
252
|
|
263
|
-
def self.efficient_dir_copy from, to
|
253
|
+
def self.efficient_dir_copy from, to, override
|
264
254
|
from.storage.open_fs{|fs|
|
265
|
-
fs.respond_to?(:efficient_dir_copy) and fs.efficient_dir_copy(from, to)
|
255
|
+
fs.respond_to?(:efficient_dir_copy) and fs.efficient_dir_copy(from, to, override)
|
266
256
|
} or
|
267
257
|
to.storage.open_fs{|fs|
|
268
|
-
fs.respond_to?(:efficient_dir_copy) and fs.efficient_dir_copy(from, to)
|
258
|
+
fs.respond_to?(:efficient_dir_copy) and fs.efficient_dir_copy(from, to, override)
|
269
259
|
}
|
270
260
|
end
|
271
261
|
end
|
data/lib/vfs/entries/entry.rb
CHANGED
@@ -73,14 +73,11 @@ module Vfs
|
|
73
73
|
not_implemented
|
74
74
|
end
|
75
75
|
|
76
|
-
def dir
|
77
|
-
|
78
|
-
|
76
|
+
def dir?; !!get(:dir) end
|
77
|
+
def file?; !!get(:file) end
|
78
|
+
|
79
|
+
include SpecialAttributes
|
79
80
|
|
80
|
-
def file?
|
81
|
-
!!get(:file)
|
82
|
-
end
|
83
|
-
|
84
81
|
|
85
82
|
#
|
86
83
|
# Micelaneous
|
@@ -101,6 +98,10 @@ module Vfs
|
|
101
98
|
end
|
102
99
|
end
|
103
100
|
|
101
|
+
def local?
|
102
|
+
storage.local?
|
103
|
+
end
|
104
|
+
|
104
105
|
|
105
106
|
#
|
106
107
|
# Utils
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Vfs
|
2
|
+
class Entry
|
3
|
+
module SpecialAttributes
|
4
|
+
def created_at
|
5
|
+
safe_get :created_at
|
6
|
+
end
|
7
|
+
|
8
|
+
def updated_at
|
9
|
+
safe_get :updated_at
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
def safe_get name
|
14
|
+
if value = get[name]
|
15
|
+
value
|
16
|
+
else
|
17
|
+
if get[:dir] or get[:file]
|
18
|
+
raise "attribute :#{name} not supported for #{storage.class}!"
|
19
|
+
else
|
20
|
+
raise "entry #{path} not exist!"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/vfs/entries/file.rb
CHANGED
data/lib/vfs/storages/hash_fs.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
#
|
2
|
+
# Very dirty and uneficient In Memory FS, mainly for tests.
|
3
3
|
#
|
4
4
|
module Vfs
|
5
5
|
module Storages
|
@@ -98,7 +98,7 @@ module Vfs
|
|
98
98
|
# raise 'not supported'
|
99
99
|
# end
|
100
100
|
|
101
|
-
def
|
101
|
+
def each_entry path, &block
|
102
102
|
base, name = split_path path
|
103
103
|
assert cd(base)[name], :include?, :dir
|
104
104
|
cd(base)[name].each do |relative_name, content|
|
@@ -111,27 +111,47 @@ module Vfs
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
def efficient_dir_copy from, to
|
114
|
+
def efficient_dir_copy from, to, override
|
115
115
|
from.storage.open_fs do |from_fs|
|
116
116
|
to.storage.open_fs do |to_fs|
|
117
117
|
if from_fs == to_fs
|
118
118
|
for_spec_helper_effective_copy_used
|
119
119
|
|
120
|
-
|
121
|
-
assert cd(from_base)[from_name], :include?, :dir
|
122
|
-
|
123
|
-
to_base, to_name = split_path to.path
|
124
|
-
assert_not cd(to_base), :include?, to_name
|
125
|
-
|
126
|
-
cd(to_base)[to_name] = cd(from_base)[from_name]
|
127
|
-
|
120
|
+
_efficient_dir_copy from.path, to.path, override
|
128
121
|
true
|
129
122
|
else
|
130
123
|
false
|
131
124
|
end
|
132
125
|
end
|
133
126
|
end
|
134
|
-
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def _efficient_dir_copy from_path, to_path, override
|
130
|
+
from_base, from_name = split_path from_path
|
131
|
+
assert cd(from_base)[from_name], :include?, :dir
|
132
|
+
|
133
|
+
to_base, to_name = split_path to_path
|
134
|
+
# assert_not cd(to_base), :include?, to_name
|
135
|
+
|
136
|
+
if cd(to_base).include? to_name
|
137
|
+
if cd(to_base)[to_name][:dir]
|
138
|
+
each_entry from_path do |name, type|
|
139
|
+
if type == :dir
|
140
|
+
_efficient_dir_copy "#{from_path}/#{name}", "#{to_path}/#{name}", override
|
141
|
+
else
|
142
|
+
raise "file #{to_path}/#{name} already exist!" if cd(to_base)[to_name].include?(name) and !override
|
143
|
+
cd(to_base)[to_name][name] = cd(from_base)[from_name][name].clone
|
144
|
+
end
|
145
|
+
end
|
146
|
+
else
|
147
|
+
raise "can't copy dir #{from_path} to file #{to_path}!"
|
148
|
+
end
|
149
|
+
else
|
150
|
+
cd(to_base)[to_name] = {dir: true}
|
151
|
+
_efficient_dir_copy from_path, to_path, override
|
152
|
+
end
|
153
|
+
end
|
154
|
+
protected :_efficient_dir_copy
|
135
155
|
def for_spec_helper_effective_copy_used; end
|
136
156
|
|
137
157
|
# def upload_directory from_local_path, to_remote_path
|
data/lib/vfs/storages/local.rb
CHANGED
@@ -19,6 +19,10 @@ module Vfs
|
|
19
19
|
attrs = {}
|
20
20
|
attrs[:file] = stat.file?
|
21
21
|
attrs[:dir] = stat.directory?
|
22
|
+
|
23
|
+
# attributes special for file system
|
24
|
+
attrs[:created_at] = stat.ctime
|
25
|
+
attrs[:updated_at] = stat.mtime
|
22
26
|
attrs
|
23
27
|
rescue Errno::ENOENT
|
24
28
|
{}
|
@@ -68,7 +72,7 @@ module Vfs
|
|
68
72
|
FileUtils.rm_r path
|
69
73
|
end
|
70
74
|
|
71
|
-
def
|
75
|
+
def each_entry path, &block
|
72
76
|
::Dir.foreach path do |relative_name|
|
73
77
|
next if relative_name == '.' or relative_name == '..'
|
74
78
|
if ::File.directory? "#{path}/#{relative_name}"
|
@@ -79,7 +83,9 @@ module Vfs
|
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
82
|
-
def efficient_dir_copy from, to
|
86
|
+
def efficient_dir_copy from, to, override
|
87
|
+
return false if override # FileUtils.cp_r doesn't support this behaviour
|
88
|
+
|
83
89
|
from.storage.open_fs do |from_fs|
|
84
90
|
to.storage.open_fs do |to_fs|
|
85
91
|
if from_fs.local? and to_fs.local?
|
@@ -20,6 +20,8 @@ shared_examples_for 'vfs storage' do
|
|
20
20
|
@storage.open_fs{|fs| fs.should respond_to(:local?)}
|
21
21
|
end
|
22
22
|
|
23
|
+
it 'should respond to :host'
|
24
|
+
|
23
25
|
it 'should have root dir' do
|
24
26
|
@storage.open_fs do |fs|
|
25
27
|
fs.attributes('/').subset(:file, :dir).should == {file: false, dir: true}
|
@@ -99,7 +101,7 @@ shared_examples_for 'vfs storage' do
|
|
99
101
|
it 'each' do
|
100
102
|
@storage.open_fs do |fs|
|
101
103
|
list = {}
|
102
|
-
fs.
|
104
|
+
fs.each_entry(@tmp_dir){|path, type| list[path] = type}
|
103
105
|
list.should be_empty
|
104
106
|
|
105
107
|
dir, file = "#{@tmp_dir}/dir", "#{@tmp_dir}/file"
|
@@ -107,7 +109,7 @@ shared_examples_for 'vfs storage' do
|
|
107
109
|
fs.write_file(file, false){|w| w.call 'something'}
|
108
110
|
|
109
111
|
list = {}
|
110
|
-
fs.
|
112
|
+
fs.each_entry(@tmp_dir){|path, type| list[path] = type}
|
111
113
|
list.should == {'dir' => :dir, 'file' => :file}
|
112
114
|
end
|
113
115
|
end
|
data/lib/vfs/vfs.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Vfs
|
2
|
+
class << self
|
3
|
+
def to_entry
|
4
|
+
'/'.to_entry
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_file
|
8
|
+
to_entry.file
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_dir
|
12
|
+
to_entry.dir
|
13
|
+
end
|
14
|
+
|
15
|
+
# def [] path
|
16
|
+
# to_entry[path]
|
17
|
+
# end
|
18
|
+
# alias_method :/, :[]
|
19
|
+
|
20
|
+
%w(
|
21
|
+
entry dir file
|
22
|
+
entries dirs files
|
23
|
+
[] /
|
24
|
+
tmp
|
25
|
+
).each do |m|
|
26
|
+
script = <<-RUBY
|
27
|
+
def #{m} *a, &b
|
28
|
+
to_entry.#{m} *a, &b
|
29
|
+
end
|
30
|
+
RUBY
|
31
|
+
eval script, binding, __FILE__, __LINE__
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/readme.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Vfs - Virtual File System
|
2
2
|
|
3
3
|
Handy and simple abstraction over any storage that can represent concept of File and Directory (or at least part of it).
|
4
|
-
The Vfs for File System
|
4
|
+
The Vfs for File System is the same as ActiveRecord is for Relational Databases.
|
5
5
|
|
6
6
|
Currently, there are following implementations available:
|
7
7
|
|
@@ -20,69 +20,76 @@ Currently, there are following implementations available:
|
|
20
20
|
** all methods should have the same performance as native system calls, except for :move and :rename. Right now they are implemented
|
21
21
|
ASAP by using copy+destroy approach, will be fixed as soon as I'll have free time to do it.
|
22
22
|
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
$ gem install vfs
|
26
|
+
$ gem install vos
|
27
|
+
|
23
28
|
## Code samples:
|
24
|
-
|
25
|
-
|
29
|
+
gem 'vfs' # Virtual File System
|
30
|
+
require 'vfs'
|
26
31
|
|
27
|
-
|
28
|
-
|
32
|
+
gem 'vos' # Virtual Operating System
|
33
|
+
require 'vos'
|
29
34
|
|
30
35
|
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
# Connections, let's deploy our 'cool_app' project from our local box to remote server
|
37
|
+
server = Box.new('cool_app.com') # it will use id_rsa, or You can add {user: 'me', password: 'secret'}
|
38
|
+
me = '~'.to_dir # handy shortcut for local FS
|
34
39
|
|
35
|
-
|
36
|
-
|
40
|
+
deploy_dir = server['apps/cool_app']
|
41
|
+
projects = me['projects']
|
37
42
|
|
38
43
|
|
39
|
-
|
40
|
-
|
44
|
+
# Working with dirs, copying dir from any source to any destination (local/remote/custom_storage_type)
|
45
|
+
projects['cool_app'].copy_to deploy_dir
|
41
46
|
|
42
47
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
# Working with files
|
49
|
+
dbc = deploy_dir.file('config/database.yml') # <= the 'config' dir not exist yet
|
50
|
+
dbc.write("user: root\npassword: secret") # <= now the 'database.yml' and parent 'config' has been created
|
51
|
+
dbc.content =~ /database/ # => false, we forgot to add the database
|
52
|
+
dbc.append("\ndatabase: mysql") # let's do it
|
48
53
|
|
49
|
-
|
50
|
-
|
51
|
-
|
54
|
+
dbc.update do |content| # and add host info
|
55
|
+
content + "\nhost: cool_app.com "
|
56
|
+
end
|
52
57
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
projects['cool_app/config/database.yml']. # or just overwrite it with our local dev version
|
59
|
+
copy_to! dbc
|
60
|
+
|
61
|
+
# there are also streaming support (read/write/append) with &block, please go to specs for details
|
57
62
|
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
64
|
+
# Checks
|
65
|
+
deploy_dir['config'].exist? # => true
|
66
|
+
deploy_dir.dir('config').exist? # => true
|
67
|
+
deploy_dir.file('config').exist? # => false
|
63
68
|
|
64
|
-
|
65
|
-
|
69
|
+
deploy_dir['config'].dir? # => true
|
70
|
+
deploy_dir['config'].file? # => false
|
66
71
|
|
67
72
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
+
# Navigation
|
74
|
+
config = deploy_dir['config']
|
75
|
+
config.parent # => </apps/cool_app>
|
76
|
+
config['../..'] # => </>
|
77
|
+
config['../..'].dir? # => true
|
73
78
|
|
74
|
-
|
75
|
-
|
76
|
-
|
79
|
+
deploy_dir.entries # => list of dirs and files, also support &block
|
80
|
+
deploy_dir.files # => list of files, also support &block
|
81
|
+
deploy_dir.dirs # => list of dirs, also support &block
|
77
82
|
|
78
83
|
|
79
|
-
|
84
|
+
# For more please go to specs (create/update/move/copy/destroy/...)
|
80
85
|
|
81
86
|
## Integration with [Vos][vos] (Virtual Operating System)
|
82
87
|
|
83
|
-
|
88
|
+
server['apps/cool_app'].bash 'rails production'
|
84
89
|
|
85
|
-
For more details please go to [Vos][vos] project page.
|
90
|
+
For more details please go to [Vos][vos] project page.
|
91
|
+
Or checkout configuration I use to control my production servers [My Cluster][my_cluster] in conjunction with small
|
92
|
+
configuration tool [Cluster Management][cluster_management].
|
86
93
|
|
87
94
|
# Why?
|
88
95
|
|
@@ -103,7 +110,7 @@ different API than local FS, and you has to remember all thouse little quirks).
|
|
103
110
|
- list of entries/files/dirs
|
104
111
|
- support for efficient copy for Local and SSH storages
|
105
112
|
|
106
|
-
### v 0.2
|
113
|
+
### v 0.2
|
107
114
|
|
108
115
|
- efficient (not copy/destroy) versions of move_to, rename
|
109
116
|
- glob search for directories: Dir['**/*.yml']
|
@@ -114,4 +121,6 @@ different API than local FS, and you has to remember all thouse little quirks).
|
|
114
121
|
|
115
122
|
- add storages: Hadoop DFS, MongoDB, Amazon S3
|
116
123
|
|
117
|
-
[vos]: http://github.com/alexeypetrushin/vos
|
124
|
+
[vos]: http://github.com/alexeypetrushin/vos
|
125
|
+
[cluster_management]: http://github.com/alexeypetrushin/cluster_management
|
126
|
+
[my_cluster]: http://github.com/alexeypetrushin/my_cluster
|
data/spec/dir_spec.rb
CHANGED
@@ -121,6 +121,8 @@ describe 'Dir' do
|
|
121
121
|
@path.include?('file').should be_true
|
122
122
|
@path.include?('non_existing').should be_false
|
123
123
|
end
|
124
|
+
|
125
|
+
it 'empty?'
|
124
126
|
end
|
125
127
|
|
126
128
|
describe 'copying' do
|
@@ -137,69 +139,81 @@ describe 'Dir' do
|
|
137
139
|
-> {@from.copy_to @from}.should raise_error(Vfs::Error, /itself/)
|
138
140
|
end
|
139
141
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
142
|
+
shared_examples_for 'copy_to behavior' do
|
143
|
+
it 'should not copy to file (and overwrite if forced)' do
|
144
|
+
-> {@from.copy_to @to.file}.should raise_error(/can't copy Dir to File/)
|
145
|
+
|
146
|
+
@from.copy_to! @to.file
|
147
|
+
@to['file'].read.should == 'something'
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should not override files (and override if forced)' do
|
151
|
+
@from.copy_to @to
|
152
|
+
-> {@from.copy_to @to}.should raise_error(/already exist/)
|
153
|
+
|
154
|
+
@from['dir/file2'].write! 'another'
|
155
|
+
@from.copy_to! @to
|
156
|
+
@to['dir/file2'].read.should == 'another'
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should copy to UniversalEntry (and overwrite if forced)' do
|
160
|
+
@from.copy_to @to.entry
|
161
|
+
-> {@from.copy_to @to.entry}.should raise_error(/already exist/)
|
162
|
+
|
163
|
+
@from.copy_to! @to.entry
|
164
|
+
@to['file'].read.should == 'something'
|
165
|
+
end
|
166
|
+
|
167
|
+
it "shouldn't delete existing content of directory" do
|
168
|
+
@to.dir.create!
|
169
|
+
@to.file('existing_file').write 'existing_content'
|
170
|
+
@to.dir('existing_dir').create
|
171
|
+
@to.file('dir/existing_file2').write 'existing_content2'
|
172
|
+
|
173
|
+
@from.copy_to @to
|
174
|
+
# copied files
|
175
|
+
@to['file'].read.should == 'something'
|
176
|
+
@to['dir/file2'].read.should == 'something2'
|
177
|
+
# shouldn't delete already existing files
|
178
|
+
@to.file('existing_file').read.should == 'existing_content'
|
179
|
+
@to.dir('existing_dir').should exist
|
180
|
+
@to.file('dir/existing_file2').read.should == 'existing_content2'
|
148
181
|
end
|
149
182
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
183
|
+
it 'should be chainable' do
|
184
|
+
@from.copy_to(@to).should == @to
|
185
|
+
@from.copy_to!(@to).should == @to
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should override without deleting other files" do
|
189
|
+
@from.copy_to(@to).should == @to
|
190
|
+
@to.file('other_file').write 'other'
|
191
|
+
|
192
|
+
@from.copy_to!(@to).should == @to
|
193
|
+
@to.file('other_file').read.should == 'other'
|
194
|
+
end
|
155
195
|
end
|
156
196
|
|
157
197
|
describe 'general copy' do
|
198
|
+
it_should_behave_like 'copy_to behavior'
|
199
|
+
|
158
200
|
before :each do
|
159
201
|
# we using here another HashFs storage, to prevent :effective_dir_copy to be used
|
160
202
|
@to = '/'.to_entry_on(Vfs::Storages::HashFs.new)['to']
|
161
203
|
|
162
204
|
@from.storage.should_not_receive(:for_spec_helper_effective_copy_used)
|
163
|
-
end
|
164
|
-
|
165
|
-
it 'should copy to file (and overwrite if forced)' do
|
166
|
-
check_copy_for @to.file, /can't copy Dir to File/, /can't copy Dir to File/
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'should copy to dir (and overwrite if forced)' do
|
170
|
-
check_copy_for @to.dir, nil, /exist/
|
171
|
-
end
|
172
|
-
|
173
|
-
it 'should copy to UniversalEntry (and overwrite if forced)' do
|
174
|
-
check_copy_for @to.entry, nil, /exist/
|
175
|
-
end
|
176
|
-
end
|
205
|
+
end
|
206
|
+
end
|
177
207
|
|
178
208
|
describe 'effective copy' do
|
209
|
+
it_should_behave_like 'copy_to behavior'
|
210
|
+
|
179
211
|
before :each do
|
180
212
|
# we using the same HashFs storage, so :effective_dir_copy will be used
|
181
213
|
@to = @fs['to']
|
182
214
|
|
183
|
-
@from.storage.should_receive(:for_spec_helper_effective_copy_used).at_least(1).times
|
184
|
-
end
|
185
|
-
|
186
|
-
it 'should copy to file (and overwrite if forced)' do
|
187
|
-
check_copy_for @to.file, /can't copy Dir to File/, /can't copy Dir to File/
|
188
|
-
end
|
189
|
-
|
190
|
-
it 'should copy to dir (and overwrite if forced)' do
|
191
|
-
check_copy_for @to.dir, nil, /exist/
|
215
|
+
# @from.storage.should_receive(:for_spec_helper_effective_copy_used).at_least(1).times
|
192
216
|
end
|
193
|
-
|
194
|
-
it 'should copy to UniversalEntry (and overwrite if forced)' do
|
195
|
-
check_copy_for @to.entry, nil, /exist/
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
it 'should be chainable' do
|
200
|
-
to = @fs['to']
|
201
|
-
@from.copy_to(to).should == to
|
202
|
-
@from.copy_to!(to).should == to
|
203
217
|
end
|
204
218
|
end
|
205
219
|
|
data/spec/entry_spec.rb
CHANGED
data/spec/storages/local_spec.rb
CHANGED
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vfs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
version: 0.1.0
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.1
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Alexey Petrushin
|
@@ -14,7 +10,7 @@ autorequire:
|
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
12
|
|
17
|
-
date: 2011-02-
|
13
|
+
date: 2011-02-16 00:00:00 +03:00
|
18
14
|
default_executable:
|
19
15
|
dependencies: []
|
20
16
|
|
@@ -30,6 +26,7 @@ files:
|
|
30
26
|
- Rakefile
|
31
27
|
- readme.md
|
32
28
|
- lib/vfs/entries/dir.rb
|
29
|
+
- lib/vfs/entries/entry/special_attributes.rb
|
33
30
|
- lib/vfs/entries/entry.rb
|
34
31
|
- lib/vfs/entries/file.rb
|
35
32
|
- lib/vfs/entries/universal_entry.rb
|
@@ -41,6 +38,7 @@ files:
|
|
41
38
|
- lib/vfs/storages/local.rb
|
42
39
|
- lib/vfs/storages/specification.rb
|
43
40
|
- lib/vfs/support.rb
|
41
|
+
- lib/vfs/vfs.rb
|
44
42
|
- lib/vfs.rb
|
45
43
|
- spec/container_spec.rb
|
46
44
|
- spec/dir_spec.rb
|
@@ -65,21 +63,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
65
63
|
requirements:
|
66
64
|
- - ">="
|
67
65
|
- !ruby/object:Gem::Version
|
68
|
-
segments:
|
69
|
-
- 0
|
70
66
|
version: "0"
|
71
67
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
68
|
none: false
|
73
69
|
requirements:
|
74
70
|
- - ">="
|
75
71
|
- !ruby/object:Gem::Version
|
76
|
-
segments:
|
77
|
-
- 0
|
78
72
|
version: "0"
|
79
73
|
requirements: []
|
80
74
|
|
81
75
|
rubyforge_project:
|
82
|
-
rubygems_version: 1.
|
76
|
+
rubygems_version: 1.5.1
|
83
77
|
signing_key:
|
84
78
|
specification_version: 3
|
85
79
|
summary: Virtual File System
|