vfs 0.3.12 → 0.3.13
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/lib/vfs.rb +5 -5
- data/lib/vfs/entries/dir.rb +65 -65
- data/lib/vfs/entries/entry.rb +38 -38
- data/lib/vfs/entries/entry/special_attributes.rb +2 -2
- data/lib/vfs/entries/file.rb +46 -46
- data/lib/vfs/entries/universal_entry.rb +5 -5
- data/lib/vfs/entry_proxy.rb +10 -10
- data/lib/vfs/integration/string.rb +4 -4
- data/lib/vfs/path.rb +25 -25
- data/lib/vfs/storages/local.rb +29 -29
- data/lib/vfs/storages/specification.rb +27 -27
- data/lib/vfs/vfs.rb +7 -7
- data/readme.md +14 -35
- data/spec/container_spec.rb +5 -5
- data/spec/dir_spec.rb +49 -49
- data/spec/entry_spec.rb +9 -9
- data/spec/file_spec.rb +47 -47
- data/spec/path_spec.rb +31 -31
- data/spec/spec_helper.rb +11 -11
- data/spec/storages/local_spec.rb +4 -4
- data/spec/universal_entry_spec.rb +9 -9
- metadata +1 -1
data/lib/vfs/entries/file.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Vfs
|
2
2
|
class File < Entry
|
3
|
-
#
|
3
|
+
#
|
4
4
|
# Attributes
|
5
|
-
#
|
5
|
+
#
|
6
6
|
alias_method :exist?, :file?
|
7
|
-
|
8
|
-
|
7
|
+
|
8
|
+
|
9
9
|
#
|
10
10
|
# CRUD
|
11
11
|
#
|
@@ -33,38 +33,38 @@ module Vfs
|
|
33
33
|
raise Error, "file #{self} not exist!"
|
34
34
|
else
|
35
35
|
block ? block.call('') : ''
|
36
|
-
end
|
36
|
+
end
|
37
37
|
end
|
38
38
|
end
|
39
|
-
end
|
39
|
+
end
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def content options = {}
|
43
43
|
read options
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
def create options = {}
|
47
47
|
write '', options
|
48
48
|
self
|
49
|
-
end
|
49
|
+
end
|
50
50
|
def create! options = {}
|
51
51
|
options[:override] = true
|
52
52
|
create options
|
53
53
|
end
|
54
|
-
|
55
|
-
def write *args, &block
|
56
|
-
storage.open_fs do |fs|
|
54
|
+
|
55
|
+
def write *args, &block
|
56
|
+
storage.open_fs do |fs|
|
57
57
|
try = 0
|
58
58
|
begin
|
59
59
|
try += 1
|
60
60
|
if block
|
61
|
-
options = args.first || {}
|
61
|
+
options = args.first || {}
|
62
62
|
else
|
63
63
|
data, options = *args
|
64
|
-
options ||= {}
|
64
|
+
options ||= {}
|
65
65
|
end
|
66
|
-
raise "can't do :override and :append at the same time!" if options[:override] and options[:append]
|
67
|
-
if block
|
66
|
+
raise "can't do :override and :append at the same time!" if options[:override] and options[:append]
|
67
|
+
if block
|
68
68
|
fs.write_file(path, options[:append], &block)
|
69
69
|
else
|
70
70
|
fs.write_file(path, options[:append]){|writer| writer.write data}
|
@@ -81,9 +81,9 @@ module Vfs
|
|
81
81
|
parent = self.parent
|
82
82
|
if parent.exist?
|
83
83
|
# some unknown error
|
84
|
-
raise error
|
84
|
+
raise error
|
85
85
|
else
|
86
|
-
parent.create(options)
|
86
|
+
parent.create(options)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -91,23 +91,23 @@ module Vfs
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
self
|
94
|
-
end
|
94
|
+
end
|
95
95
|
def write! *args, &block
|
96
96
|
args << {} unless args.last.is_a? Hash
|
97
97
|
args.last[:override] = true
|
98
98
|
write *args, &block
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
def destroy options = {}
|
102
|
-
storage.open_fs do |fs|
|
102
|
+
storage.open_fs do |fs|
|
103
103
|
begin
|
104
|
-
fs.delete_file path
|
104
|
+
fs.delete_file path
|
105
105
|
self
|
106
106
|
rescue StandardError => e
|
107
107
|
attrs = get
|
108
108
|
if attrs[:dir]
|
109
109
|
if options[:force]
|
110
|
-
dir.destroy
|
110
|
+
dir.destroy
|
111
111
|
else
|
112
112
|
raise Error, "can't destroy Dir #{dir} (you are trying to destroy it as if it's a File)"
|
113
113
|
end
|
@@ -125,53 +125,53 @@ module Vfs
|
|
125
125
|
options[:force] = true
|
126
126
|
destroy options
|
127
127
|
end
|
128
|
-
|
128
|
+
|
129
129
|
def append *args, &block
|
130
130
|
if block
|
131
|
-
options = args.first || {}
|
131
|
+
options = args.first || {}
|
132
132
|
else
|
133
133
|
data, options = *args
|
134
|
-
options ||= {}
|
134
|
+
options ||= {}
|
135
135
|
end
|
136
|
-
|
136
|
+
|
137
137
|
options[:append] = true
|
138
138
|
write data, options, &block
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
def update options = {}, &block
|
142
142
|
options[:override] = true
|
143
143
|
data = read options
|
144
144
|
write block.call(data), options
|
145
145
|
end
|
146
|
-
|
147
|
-
|
146
|
+
|
147
|
+
|
148
148
|
#
|
149
149
|
# Transfers
|
150
|
-
#
|
150
|
+
#
|
151
151
|
def copy_to to, options = {}
|
152
152
|
raise Error, "you can't copy to itself" if self == to
|
153
|
-
|
153
|
+
|
154
154
|
target = if to.is_a? File
|
155
155
|
to
|
156
156
|
elsif to.is_a? Dir
|
157
|
-
to.file #(name)
|
157
|
+
to.file #(name)
|
158
158
|
elsif to.is_a? UniversalEntry
|
159
|
-
to.file
|
159
|
+
to.file
|
160
160
|
else
|
161
161
|
raise "can't copy to unknown Entry!"
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
target.write options do |writer|
|
165
165
|
read(options){|buff| writer.write buff}
|
166
166
|
end
|
167
|
-
|
167
|
+
|
168
168
|
target
|
169
169
|
end
|
170
170
|
def copy_to! to, options = {}
|
171
171
|
options[:override] = true
|
172
172
|
copy_to to, options
|
173
173
|
end
|
174
|
-
|
174
|
+
|
175
175
|
def move_to to, options = {}
|
176
176
|
copy_to to, options
|
177
177
|
destroy options
|
@@ -181,28 +181,28 @@ module Vfs
|
|
181
181
|
options[:override] = true
|
182
182
|
move_to to, options
|
183
183
|
end
|
184
|
-
|
185
|
-
|
186
|
-
#
|
184
|
+
|
185
|
+
|
186
|
+
#
|
187
187
|
# Extra Stuff
|
188
|
-
#
|
188
|
+
#
|
189
189
|
def render *args
|
190
190
|
require 'tilt'
|
191
|
-
|
191
|
+
|
192
192
|
args.unshift Object.new if args.size == 1 and args.first.is_a?(Hash)
|
193
|
-
|
193
|
+
|
194
194
|
template = Tilt.new(path){read}
|
195
195
|
template.render *args
|
196
196
|
end
|
197
|
-
|
197
|
+
|
198
198
|
def size
|
199
199
|
get :size
|
200
200
|
end
|
201
|
-
|
201
|
+
|
202
202
|
def basename
|
203
203
|
::File.basename(name, File.extname(name))
|
204
204
|
end
|
205
|
-
|
205
|
+
|
206
206
|
def extension
|
207
207
|
::File.extname(name).sub(/^\./, '')
|
208
208
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
module Vfs
|
2
2
|
class UniversalEntry < Entry
|
3
|
-
#
|
3
|
+
#
|
4
4
|
# Attributes
|
5
|
-
#
|
5
|
+
#
|
6
6
|
def exist?
|
7
7
|
attrs = get
|
8
8
|
!!(attrs[:dir] or attrs[:file])
|
9
9
|
end
|
10
|
-
|
11
|
-
|
10
|
+
|
11
|
+
|
12
12
|
#
|
13
13
|
# CRUD
|
14
14
|
#
|
15
15
|
def destroy
|
16
16
|
storage.open_fs do |fs|
|
17
|
-
attrs = get
|
17
|
+
attrs = get
|
18
18
|
fs.delete_dir path if attrs[:dir]
|
19
19
|
fs.delete_file path if attrs[:file]
|
20
20
|
end
|
data/lib/vfs/entry_proxy.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
#
|
1
|
+
#
|
2
2
|
# It allows you dynamically (magically) switch between UniversalEntry/Dir/File
|
3
|
-
#
|
3
|
+
#
|
4
4
|
module Vfs
|
5
|
-
class EntryProxy < BasicObject
|
5
|
+
class EntryProxy < BasicObject
|
6
6
|
attr_reader :_target
|
7
7
|
# WRAP = [:[], :entry, :dir, :file].to_set
|
8
|
-
|
8
|
+
|
9
9
|
def initialize entry
|
10
10
|
raise 'something wrong happening here!' if entry.respond_to?(:proxy?) and entry.proxy?
|
11
11
|
self._target = entry
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def proxy?
|
15
15
|
true
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
protected :==, :equal?, :!, :!=
|
19
|
-
protected
|
19
|
+
protected
|
20
20
|
attr_writer :_target
|
21
|
-
|
21
|
+
|
22
22
|
def method_missing m, *a, &b
|
23
23
|
unless _target.respond_to? m
|
24
24
|
if ::Vfs::UniversalEntry.method_defined? m
|
@@ -29,9 +29,9 @@ module Vfs
|
|
29
29
|
self._target = _target.file
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
_target.send m, *a, &b
|
34
|
-
|
34
|
+
|
35
35
|
# return WRAP.include?(m) ? EntryProxy.new(result) : result
|
36
36
|
end
|
37
37
|
end
|
@@ -2,16 +2,16 @@ class String
|
|
2
2
|
def to_entry_on storage = nil
|
3
3
|
path = self
|
4
4
|
storage ||= Vfs.default_storage
|
5
|
-
|
5
|
+
|
6
6
|
Vfs::Dir.new(storage, '/')[path]
|
7
7
|
end
|
8
|
-
alias_method :to_entry, :to_entry_on
|
9
|
-
|
8
|
+
alias_method :to_entry, :to_entry_on
|
9
|
+
|
10
10
|
def to_file_on storage = nil
|
11
11
|
to_entry_on(storage).file
|
12
12
|
end
|
13
13
|
alias_method :to_file, :to_file_on
|
14
|
-
|
14
|
+
|
15
15
|
def to_dir_on storage = nil
|
16
16
|
to_entry_on(storage).dir
|
17
17
|
end
|
data/lib/vfs/path.rb
CHANGED
@@ -10,13 +10,13 @@ module Vfs
|
|
10
10
|
raise "invalid path '#{path}' (you are outside of the root)!" unless path
|
11
11
|
super path
|
12
12
|
@probably_dir = probably_dir
|
13
|
-
end
|
13
|
+
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def + path = ''
|
17
17
|
path = path.to_s
|
18
18
|
Path.validate! path, false
|
19
|
-
|
19
|
+
|
20
20
|
if Path.absolute?(path)
|
21
21
|
Path.normalize path
|
22
22
|
elsif path.empty?
|
@@ -25,15 +25,15 @@ module Vfs
|
|
25
25
|
Path.normalize "#{self}#{'/' unless self == '/'}#{path}"
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def parent
|
30
30
|
self + '..'
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def probably_dir?
|
34
34
|
!!@probably_dir
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def name
|
38
38
|
unless @name
|
39
39
|
root = self[0..0]
|
@@ -41,12 +41,12 @@ module Vfs
|
|
41
41
|
end
|
42
42
|
@name
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
class << self
|
46
46
|
def absolute? path
|
47
47
|
path =~ /^[\/~\/]|^\.$|^\.\//
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
def valid? path, forbid_relative = true, &block
|
51
51
|
result, err = if forbid_relative and !absolute?(path)
|
52
52
|
[false, "path must be started with '/', or '.'"]
|
@@ -59,28 +59,28 @@ module Vfs
|
|
59
59
|
else
|
60
60
|
[true, nil]
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
block.call err if block and !result and err
|
64
64
|
result
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
def normalize path
|
68
68
|
path, probably_dir = normalize_to_string path
|
69
|
-
unless path
|
69
|
+
unless path
|
70
70
|
nil
|
71
71
|
else
|
72
72
|
Path.new(path, skip_normalization: true, probably_dir: probably_dir)
|
73
73
|
end
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
def validate! path, forbid_relative = true
|
77
77
|
valid?(path, forbid_relative){|error| raise "invalid path '#{path}' (#{error})!"}
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
def normalize_to_string path
|
81
|
-
root = path[0..0]
|
81
|
+
root = path[0..0]
|
82
82
|
result, probably_dir = [], false
|
83
|
-
|
83
|
+
|
84
84
|
parts = path.split('/')[1..-1]
|
85
85
|
if parts
|
86
86
|
parts.each do |part|
|
@@ -95,29 +95,29 @@ module Vfs
|
|
95
95
|
probably_dir &&= false
|
96
96
|
end
|
97
97
|
end
|
98
|
-
end
|
99
|
-
normalized_path = result.join('/')
|
100
|
-
|
98
|
+
end
|
99
|
+
normalized_path = result.join('/')
|
100
|
+
|
101
101
|
probably_dir ||= true if normalized_path.empty?
|
102
102
|
|
103
103
|
return "#{root}#{'/' unless root == '/' or normalized_path.empty?}#{normalized_path}", probably_dir
|
104
104
|
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# protected
|
105
|
+
end
|
106
|
+
|
107
|
+
# protected
|
108
108
|
# def delete_dir_mark
|
109
109
|
# path = path.to_s.sub(%r{/$}, '')
|
110
110
|
# end
|
111
|
-
#
|
112
|
-
#
|
111
|
+
#
|
112
|
+
#
|
113
113
|
# def root_path? path
|
114
114
|
# path =~ /^[#{ROOT_SYMBOLS}]$/
|
115
115
|
# end
|
116
|
-
#
|
116
|
+
#
|
117
117
|
# def split_path path
|
118
118
|
# path.split(/#{ROOT_SYMBOLS}/)
|
119
119
|
# end
|
120
|
-
#
|
120
|
+
#
|
121
121
|
# def dir_mark? path
|
122
122
|
# path =~ %r{/$}
|
123
123
|
# end
|
data/lib/vfs/storages/local.rb
CHANGED
@@ -8,29 +8,29 @@ module Vfs
|
|
8
8
|
def initialize out
|
9
9
|
@out = out
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def write data
|
13
13
|
@out.write data
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
module LocalVfsHelper
|
18
18
|
DEFAULT_BUFFER = 1000 * 1024
|
19
|
-
|
19
|
+
|
20
20
|
attr_writer :buffer
|
21
21
|
def buffer
|
22
22
|
@buffer || DEFAULT_BUFFER
|
23
|
-
end
|
24
|
-
|
25
|
-
#
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
26
|
# Attributes
|
27
|
-
#
|
27
|
+
#
|
28
28
|
def attributes path
|
29
29
|
stat = ::File.stat path
|
30
30
|
attrs = {}
|
31
31
|
attrs[:file] = stat.file?
|
32
32
|
attrs[:dir] = stat.directory?
|
33
|
-
|
33
|
+
|
34
34
|
# attributes special for file system
|
35
35
|
attrs[:created_at] = stat.ctime
|
36
36
|
attrs[:updated_at] = stat.mtime
|
@@ -40,17 +40,17 @@ module Vfs
|
|
40
40
|
{}
|
41
41
|
end
|
42
42
|
|
43
|
-
def set_attributes path, attrs
|
43
|
+
def set_attributes path, attrs
|
44
44
|
raise 'not supported'
|
45
45
|
end
|
46
46
|
|
47
47
|
|
48
|
-
#
|
48
|
+
#
|
49
49
|
# File
|
50
|
-
#
|
50
|
+
#
|
51
51
|
def read_file path, &block
|
52
52
|
::File.open path, 'r' do |is|
|
53
|
-
while buff = is.gets(self.buffer || DEFAULT_BUFFER)
|
53
|
+
while buff = is.gets(self.buffer || DEFAULT_BUFFER)
|
54
54
|
block.call buff
|
55
55
|
end
|
56
56
|
end
|
@@ -59,14 +59,14 @@ module Vfs
|
|
59
59
|
def write_file path, append, &block
|
60
60
|
# TODO2 Performance lost, extra call to check file existence
|
61
61
|
raise "can't write, entry #{path} already exist!" if !append and ::File.exist?(path)
|
62
|
-
|
63
|
-
option = append ? 'a' : 'w'
|
62
|
+
|
63
|
+
option = append ? 'a' : 'w'
|
64
64
|
::File.open path, option do |out|
|
65
65
|
block.call Writer.new(out)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
def delete_file path
|
69
|
+
def delete_file path
|
70
70
|
::File.delete path
|
71
71
|
end
|
72
72
|
|
@@ -75,7 +75,7 @@ module Vfs
|
|
75
75
|
# end
|
76
76
|
|
77
77
|
|
78
|
-
#
|
78
|
+
#
|
79
79
|
# Dir
|
80
80
|
#
|
81
81
|
def create_dir path
|
@@ -85,9 +85,9 @@ module Vfs
|
|
85
85
|
def delete_dir path
|
86
86
|
# TODO2 Performance lost, extra call to check file existence
|
87
87
|
raise "can't delete file (#{path})!" if ::File.file?(path)
|
88
|
-
|
88
|
+
|
89
89
|
FileUtils.rm_r path
|
90
|
-
end
|
90
|
+
end
|
91
91
|
|
92
92
|
def each_entry path, query, &block
|
93
93
|
if query
|
@@ -111,11 +111,11 @@ module Vfs
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
114
|
-
|
115
|
-
# def efficient_dir_copy from, to, override
|
114
|
+
|
115
|
+
# def efficient_dir_copy from, to, override
|
116
116
|
# return false if override # FileUtils.cp_r doesn't support this behaviour
|
117
|
-
#
|
118
|
-
# from.storage.open_fs do |from_fs|
|
117
|
+
#
|
118
|
+
# from.storage.open_fs do |from_fs|
|
119
119
|
# to.storage.open_fs do |to_fs|
|
120
120
|
# if from_fs.local? and to_fs.local?
|
121
121
|
# FileUtils.cp_r from.path, to.path
|
@@ -127,13 +127,13 @@ module Vfs
|
|
127
127
|
# end
|
128
128
|
# end
|
129
129
|
|
130
|
-
#
|
130
|
+
#
|
131
131
|
# Other
|
132
|
-
#
|
132
|
+
#
|
133
133
|
def local?; true end
|
134
|
-
|
134
|
+
|
135
135
|
def tmp &block
|
136
|
-
tmp_dir = "#{::Dir.tmpdir}/#{rand(10**3)}"
|
136
|
+
tmp_dir = "#{::Dir.tmpdir}/#{rand(10**3)}"
|
137
137
|
if block
|
138
138
|
begin
|
139
139
|
create_dir tmp_dir
|
@@ -146,12 +146,12 @@ module Vfs
|
|
146
146
|
tmp_dir
|
147
147
|
end
|
148
148
|
end
|
149
|
-
|
149
|
+
|
150
150
|
def to_s; '' end
|
151
151
|
end
|
152
|
-
|
152
|
+
|
153
153
|
include LocalVfsHelper
|
154
|
-
|
154
|
+
|
155
155
|
def open_fs &block
|
156
156
|
block.call self
|
157
157
|
end
|