vfs 0.1.0 → 0.1.1
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/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
|