vfs-momolog 0.0.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.
Files changed (51) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/Rakefile +2 -0
  5. data/docs/basics.rb +116 -0
  6. data/docs/s3_backup.rb +29 -0
  7. data/docs/s3_backup/app/files/bos.png +0 -0
  8. data/docs/s3_basics.rb +19 -0
  9. data/docs/s3_sandbox.rb +24 -0
  10. data/docs/site/404.html +8 -0
  11. data/docs/site/basics.html +305 -0
  12. data/docs/site/index.html +8 -0
  13. data/docs/site/s3_backup.html +111 -0
  14. data/docs/site/s3_basics.html +84 -0
  15. data/docs/site/s3_sandbox.html +99 -0
  16. data/docs/site/ssh_basics.html +84 -0
  17. data/docs/site/ssh_deployment.html +125 -0
  18. data/docs/site/ssh_sandbox.html +103 -0
  19. data/docs/ssh_basics.rb +19 -0
  20. data/docs/ssh_deployment.rb +35 -0
  21. data/docs/ssh_deployment/app/app.rb +0 -0
  22. data/docs/ssh_sandbox.rb +28 -0
  23. data/lib/vfs.rb +18 -0
  24. data/lib/vfs/drivers/local.rb +180 -0
  25. data/lib/vfs/drivers/specification.rb +169 -0
  26. data/lib/vfs/entries/dir.rb +256 -0
  27. data/lib/vfs/entries/entry.rb +152 -0
  28. data/lib/vfs/entries/file.rb +155 -0
  29. data/lib/vfs/entries/universal_entry.rb +24 -0
  30. data/lib/vfs/entry_proxy.rb +42 -0
  31. data/lib/vfs/error.rb +4 -0
  32. data/lib/vfs/integration.rb +30 -0
  33. data/lib/vfs/path.rb +123 -0
  34. data/lib/vfs/version.rb +3 -0
  35. data/lib/vfs/vfs.rb +38 -0
  36. data/old/hash_fs.rb +216 -0
  37. data/old/hash_fs_spec.rb +10 -0
  38. data/readme.md +143 -0
  39. data/spec/container_spec.rb +31 -0
  40. data/spec/dir_spec.rb +253 -0
  41. data/spec/entry_spec.rb +42 -0
  42. data/spec/file_spec.rb +215 -0
  43. data/spec/misc_spec.rb +19 -0
  44. data/spec/path_spec.rb +127 -0
  45. data/spec/spec_helper.rb +50 -0
  46. data/spec/storages/local_spec.rb +24 -0
  47. data/spec/storages/local_spec/emptygit +0 -0
  48. data/spec/universal_entry_spec.rb +69 -0
  49. data/todo.md +19 -0
  50. data/vfs.gemspec +17 -0
  51. metadata +105 -0
@@ -0,0 +1,256 @@
1
+ module Vfs
2
+ class Dir < Entry
3
+ #
4
+ # Container
5
+ #
6
+ def [] path
7
+ path = path.to_s
8
+ if path =~ /.+[\/]$/
9
+ path = path.sub /\/$/, ''
10
+ dir path
11
+ elsif path =~ /\*/
12
+ entries path
13
+ else
14
+ entry path
15
+ end
16
+ end
17
+ alias_method :/, :[]
18
+
19
+
20
+ #
21
+ # Attributes
22
+ #
23
+ alias_method :exist?, :dir?
24
+
25
+
26
+ #
27
+ # CRUD
28
+ #
29
+ def create options = {}
30
+ driver.open do
31
+ try = 0
32
+ begin
33
+ try += 1
34
+ driver.create_dir path
35
+ rescue StandardError => error
36
+ entry = self.entry
37
+ attrs = entry.get
38
+ if attrs and attrs[:file] #entry.exist?
39
+ entry.destroy
40
+ elsif attrs and attrs[:dir]
41
+ # dir already exist, no need to recreate it
42
+ return self
43
+ else
44
+ parent = self.parent
45
+ if parent.exist?
46
+ # some unknown error
47
+ raise error
48
+ else
49
+ parent.create(options)
50
+ end
51
+ end
52
+
53
+ try < 2 ? retry : raise(error)
54
+ end
55
+ end
56
+ self
57
+ end
58
+
59
+ def destroy options = {}
60
+ destroy_entry :dir, :file
61
+ end
62
+
63
+
64
+ #
65
+ # Content
66
+ #
67
+ def entries *args, &block
68
+ raise "invalid arguments #{args.inspect}!" if args.size > 2
69
+ options = args.last.is_a?(Hash) ? args.pop : {}
70
+ query = args.first
71
+ options[:bang] = true unless options.include? :bang
72
+ filter = options[:filter]
73
+ type_required = options[:type]
74
+
75
+ driver.open do
76
+ begin
77
+ list = []
78
+ # query option is optional and supported only for some drivers (local driver for example)
79
+ driver.each_entry path, query do |name, type|
80
+ # for performance reasons some drivers may return the type of entry as
81
+ # optionally evaluated callback.
82
+ type = type.call if (filter or type_required) and type.is_a?(Proc)
83
+
84
+ next if name == ''
85
+ next if filter and (filter != type)
86
+
87
+ entry = if type == :dir
88
+ dir(name)
89
+ elsif type == :file
90
+ file(name)
91
+ else
92
+ entry(name)
93
+ end
94
+ block ? block.call(entry) : (list << entry)
95
+ end
96
+ block ? nil : list
97
+ rescue StandardError => error
98
+ attrs = get
99
+ if attrs and attrs[:file]
100
+ raise Error, "can't query entries on File ('#{self}')!"
101
+ elsif attrs and attrs[:dir]
102
+ # some unknown error
103
+ raise error
104
+ else
105
+ # TODO2 remove :bang
106
+ raise Error, "'#{self}' not exist!" if options[:bang]
107
+ []
108
+ end
109
+ end
110
+ end
111
+ end
112
+ alias_method :each, :entries
113
+
114
+ def files *args, &block
115
+ options = args.last.is_a?(Hash) ? args.pop : {}
116
+
117
+ options[:filter] = :file
118
+ args << options
119
+ entries *args, &block
120
+ end
121
+
122
+ def dirs *args, &block
123
+ options = args.last.is_a?(Hash) ? args.pop : {}
124
+
125
+ options[:filter] = :dir
126
+ args << options
127
+ entries *args, &block
128
+ end
129
+
130
+ def include? name
131
+ entry[name].exist?
132
+ end
133
+ alias_method :has?, :include?
134
+
135
+ def empty?
136
+ catch :break do
137
+ entries{|e| throw :break, false}
138
+ true
139
+ end
140
+ end
141
+
142
+
143
+ #
144
+ # Transfers
145
+ #
146
+ def copy_to to, options = {}
147
+ options[:bang] = true unless options.include? :bang
148
+
149
+ raise Error, "invalid argument, destination should be a Entry (#{to})!" unless to.is_a? Entry
150
+ raise Error, "you can't copy to itself" if self == to
151
+
152
+ target = if to.is_a? File
153
+ to.dir
154
+ elsif to.is_a? Dir
155
+ to.dir #(name)
156
+ elsif to.is_a? UniversalEntry
157
+ # raise "can't copy Dir to File ('#{self}')!" if to.file? and !options[:override]
158
+ to.dir #.create
159
+ else
160
+ raise "can't copy to unknown Entry!"
161
+ end
162
+
163
+ # efficient_dir_copy(target, options) || unefficient_dir_copy(target, options)
164
+ unefficient_dir_copy(target, options)
165
+
166
+ target
167
+ end
168
+
169
+ def move_to to, options = {}
170
+ copy_to to, options
171
+ destroy options
172
+ to
173
+ end
174
+
175
+ # class << self
176
+ # attr_accessor :dont_use_efficient_dir_copy
177
+ # end
178
+
179
+ protected
180
+ def unefficient_dir_copy to, options
181
+ to.create options
182
+ entries options.merge(type: true) do |e|
183
+ if e.is_a? Dir
184
+ e.copy_to to.dir(e.name), options
185
+ elsif e.is_a? File
186
+ e.copy_to to.file(e.name), options
187
+ else
188
+ raise 'internal error'
189
+ end
190
+ end
191
+ end
192
+
193
+
194
+ # def efficient_dir_copy to, options
195
+ # return false if self.class.dont_use_efficient_dir_copy
196
+ #
197
+ # driver.open do
198
+ # try = 0
199
+ # begin
200
+ # try += 1
201
+ # self.class.efficient_dir_copy(self, to, options[:override])
202
+ # rescue StandardError => error
203
+ # unknown_errors = 0
204
+ #
205
+ # attrs = get
206
+ # if attrs and attrs[:file]
207
+ # raise Error, "can't copy File as a Dir ('#{self}')!"
208
+ # elsif attrs and attrs[:dir]
209
+ # # some unknown error (but it also maybe caused by to be fixed error in 'to')
210
+ # unknown_errors += 1
211
+ # else
212
+ # raise Error, "'#{self}' not exist!" if options[:bang]
213
+ # return true
214
+ # end
215
+ #
216
+ # attrs = to.get
217
+ # if attrs and attrs[:file]
218
+ # if options[:override]
219
+ # to.destroy
220
+ # else
221
+ # raise Vfs::Error, "entry #{to} already exist!"
222
+ # end
223
+ # elsif attrs and attrs[:dir]
224
+ # unknown_errors += 1
225
+ # # if options[:override]
226
+ # # to.destroy
227
+ # # else
228
+ # # dir_already_exist = true
229
+ # # # raise Vfs::Error, "entry #{to} already exist!"
230
+ # # end
231
+ # else # parent not exist
232
+ # parent = to.parent
233
+ # if parent.exist?
234
+ # # some unknown error (but it also maybe caused by already fixed error in 'from')
235
+ # unknown_errors += 1
236
+ # else
237
+ # parent.create(options)
238
+ # end
239
+ # end
240
+ #
241
+ # raise error if unknown_errors > 1
242
+ # try < 2 ? retry : raise(error)
243
+ # end
244
+ # end
245
+ # end
246
+ #
247
+ # def self.efficient_dir_copy from, to, override
248
+ # from.driver.open{
249
+ # driver.respond_to?(:efficient_dir_copy) and driver.efficient_dir_copy(from, to, override)
250
+ # } or
251
+ # to.driver.open{
252
+ # driver.respond_to?(:efficient_dir_copy) and driver.efficient_dir_copy(from, to, override)
253
+ # }
254
+ # end
255
+ end
256
+ end
@@ -0,0 +1,152 @@
1
+ module Vfs
2
+ class Entry
3
+ attr_reader :driver, :path, :path_cache
4
+
5
+ def initialize *args
6
+ if args.size == 1 and args.first.is_a? Entry
7
+ entry = args.first
8
+ @path_cache = entry.path_cache
9
+ @driver, @path = entry.driver, entry.path
10
+ else
11
+ driver, path = *args
12
+ @path_cache = Path.new path
13
+ @driver, @path = driver, path_cache.to_s
14
+ end
15
+ raise "driver not defined!" unless self.driver
16
+ end
17
+
18
+ #
19
+ # Navigation
20
+ #
21
+ def parent
22
+ Dir.new(driver, path_cache.parent)
23
+ end
24
+
25
+
26
+ #
27
+ # Transformations
28
+ #
29
+ def dir path = nil
30
+ if path
31
+ new_path = path_cache + path
32
+ Dir.new driver, new_path
33
+ else
34
+ Dir.new self
35
+ end
36
+ end
37
+ alias_method :to_dir, :dir
38
+
39
+ def file path = nil
40
+ if path
41
+ new_path = path_cache + path
42
+ File.new driver, new_path
43
+ else
44
+ File.new self
45
+ end
46
+ end
47
+ alias_method :to_file, :file
48
+
49
+ def entry path = nil
50
+ entry = if path
51
+ new_path = path_cache + path
52
+ klass = new_path.probably_dir? ? Dir : UniversalEntry
53
+ klass.new driver, new_path
54
+ else
55
+ UniversalEntry.new self
56
+ end
57
+ EntryProxy.new entry
58
+ end
59
+ alias_method :to_entry, :entry
60
+
61
+
62
+ #
63
+ # Attributes
64
+ #
65
+ def get attr_name = nil
66
+ attrs = driver.open{driver.attributes(path)}
67
+ (attr_name and attrs) ? attrs[attr_name] : attrs
68
+ end
69
+
70
+ def set options
71
+ # TODO2 set attributes
72
+ not_implemented
73
+ end
74
+
75
+ def dir?; !!get(:dir) end
76
+ def file?; !!get(:file) end
77
+ def created_at; get :created_at end
78
+ def updated_at; get :updated_at end
79
+
80
+
81
+ #
82
+ # Miscellaneous
83
+ #
84
+ def name
85
+ path_cache.name
86
+ end
87
+
88
+ def tmp &block
89
+ driver.open do
90
+ if block
91
+ driver.tmp do |path|
92
+ block.call Dir.new(driver, path)
93
+ end
94
+ else
95
+ Dir.new driver, driver.tmp
96
+ end
97
+ end
98
+ end
99
+
100
+ def local?
101
+ driver.local?
102
+ end
103
+
104
+
105
+ #
106
+ # Utils
107
+ #
108
+ def inspect
109
+ "#{driver}#{':' unless driver.to_s.empty?}#{path}"
110
+ end
111
+ alias_method :to_s, :inspect
112
+
113
+ def == other
114
+ return false unless other.is_a? Entry
115
+ driver == other.driver and path == other.path
116
+ end
117
+
118
+ def hash
119
+ driver.hash + path.hash
120
+ end
121
+
122
+ def eql? other
123
+ return false unless other.class == self.class
124
+ driver.eql?(other.driver) and path.eql?(other.path)
125
+ end
126
+
127
+ def delete *args
128
+ raise "use :destroy!"
129
+ end
130
+ alias_method :remove, :delete
131
+
132
+ protected
133
+ def destroy_entry first = :file, second = :dir
134
+ driver.open do
135
+ begin
136
+ driver.send :"delete_#{first}", path
137
+ rescue StandardError => e
138
+ attrs = get
139
+ if attrs and attrs[first]
140
+ # some unknown error
141
+ raise e
142
+ elsif attrs and attrs[second]
143
+ driver.send :"delete_#{second}", path
144
+ else
145
+ # do nothing, entry already not exist
146
+ end
147
+ end
148
+ end
149
+ self
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,155 @@
1
+ module Vfs
2
+ class File < Entry
3
+ #
4
+ # Attributes
5
+ #
6
+ alias_method :exist?, :file?
7
+
8
+
9
+ #
10
+ # CRUD
11
+ #
12
+ def read options = {}, &block
13
+ options[:bang] = true unless options.include? :bang
14
+ driver.open do
15
+ begin
16
+ if block
17
+ driver.read_file path, &block
18
+ else
19
+ data = ""
20
+ driver.read_file(path){|buff| data << buff}
21
+ data
22
+ end
23
+ rescue StandardError => e
24
+ raise Vfs::Error, "can't read Dir #{self}!" if dir.exist?
25
+ attrs = get
26
+ if attrs and attrs[:file]
27
+ # unknown internal error
28
+ raise e
29
+ elsif attrs and attrs[:dir]
30
+ raise Error, "You are trying to read Dir '#{self}' as if it's a File!"
31
+ else
32
+ if options[:bang]
33
+ raise Error, "file #{self} not exist!"
34
+ else
35
+ block ? block.call('') : ''
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ # def content options = {}
43
+ # read options
44
+ # end
45
+
46
+ def create options = {}
47
+ write '', options
48
+ self
49
+ end
50
+
51
+ def write *args, &block
52
+ if block
53
+ options = args.first || {}
54
+ else
55
+ data, options = *args
56
+ data ||= ""
57
+ options ||= {}
58
+ end
59
+ raise "can't do :override and :append at the same time!" if options[:override] and options[:append]
60
+
61
+ driver.open do
62
+ try = 0
63
+ begin
64
+ try += 1
65
+ if block
66
+ driver.write_file(path, options[:append], &block)
67
+ else
68
+ driver.write_file(path, options[:append]){|writer| writer.write data}
69
+ end
70
+ rescue StandardError => error
71
+ parent = self.parent
72
+ if entry.exist?
73
+ entry.destroy
74
+ elsif !parent.exist?
75
+ parent.create(options)
76
+ else
77
+ # unknown error
78
+ raise error
79
+ end
80
+
81
+ try < 2 ? retry : raise(error)
82
+ end
83
+ end
84
+ self
85
+ end
86
+
87
+ def append *args, &block
88
+ options = (args.last.is_a?(Hash) && args.pop) || {}
89
+ options[:append] = true
90
+ write(*(args << options), &block)
91
+ end
92
+
93
+ def update options = {}, &block
94
+ data = read options
95
+ write block.call(data), options
96
+ end
97
+
98
+ def destroy
99
+ destroy_entry
100
+ end
101
+
102
+
103
+ #
104
+ # Transfers
105
+ #
106
+ def copy_to to, options = {}
107
+ raise Error, "you can't copy to itself" if self == to
108
+
109
+ target = if to.is_a? File
110
+ to
111
+ elsif to.is_a? Dir
112
+ to.file #(name)
113
+ elsif to.is_a? UniversalEntry
114
+ to.file
115
+ else
116
+ raise "can't copy to unknown Entry!"
117
+ end
118
+
119
+ target.write options do |writer|
120
+ read(options){|buff| writer.write buff}
121
+ end
122
+
123
+ target
124
+ end
125
+
126
+ def move_to to
127
+ copy_to to
128
+ destroy
129
+ to
130
+ end
131
+
132
+
133
+ #
134
+ # Extra Stuff
135
+ #
136
+ def render *args
137
+ require 'tilt'
138
+
139
+ args.unshift Object.new if args.size == 1 and args.first.is_a?(Hash)
140
+
141
+ template = Tilt.new(path){read}
142
+ template.render *args
143
+ end
144
+
145
+ def size; get :size end
146
+
147
+ def basename
148
+ ::File.basename(name, ::File.extname(name))
149
+ end
150
+
151
+ def extension
152
+ ::File.extname(name).sub(/^\./, '')
153
+ end
154
+ end
155
+ end