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,24 @@
1
+ module Vfs
2
+ class UniversalEntry < Entry
3
+ #
4
+ # Attributes
5
+ #
6
+ def exist?
7
+ !!get
8
+ end
9
+
10
+
11
+ def copy_to to, options = {}
12
+ from = file? ? to_file : to_dir
13
+ from.copy_to to, options
14
+ end
15
+
16
+
17
+ #
18
+ # CRUD
19
+ #
20
+ def destroy
21
+ destroy_entry
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ #
2
+ # It allows dynamically (magically) switching between UniversalEntry/Dir/File
3
+ #
4
+ module Vfs
5
+ class EntryProxy < BasicObject
6
+ attr_reader :_target
7
+
8
+ def initialize entry
9
+ raise 'something wrong happening here!' if entry.respond_to?(:proxy?) and entry.proxy?
10
+ self._target = entry
11
+ end
12
+
13
+ def proxy?
14
+ true
15
+ end
16
+
17
+ protected :==, :equal?, :!, :!=
18
+ protected
19
+ attr_writer :_target
20
+
21
+ def respond_to? m
22
+ super or
23
+ ::Vfs::UniversalEntry.method_defined?(m) or
24
+ ::Vfs::Dir.method_defined?(m) or
25
+ ::Vfs::File.method_defined?(m)
26
+ end
27
+
28
+ def method_missing m, *a, &b
29
+ unless _target.respond_to? m
30
+ if ::Vfs::UniversalEntry.method_defined? m
31
+ self.target = _target.entry
32
+ elsif ::Vfs::Dir.method_defined? m
33
+ self._target = _target.dir
34
+ elsif ::Vfs::File.method_defined? m
35
+ self._target = _target.file
36
+ end
37
+ end
38
+
39
+ _target.send m, *a, &b
40
+ end
41
+ end
42
+ end
data/lib/vfs/error.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Vfs
2
+ class Error < StandardError
3
+ end
4
+ 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/path.rb ADDED
@@ -0,0 +1,123 @@
1
+ module Vfs
2
+ class Path < String
3
+ def initialize path = '/', options = {}
4
+ if options[:skip_normalization]
5
+ super path
6
+ @probably_dir = options[:probably_dir]
7
+ else
8
+ Path.validate! path
9
+ path, probably_dir = Path.normalize_to_string path
10
+ raise "invalid path '#{path}' (you are outside of the root)!" unless path
11
+ super path
12
+ @probably_dir = probably_dir
13
+ end
14
+ end
15
+
16
+ def + path = ''
17
+ path = path.to_s
18
+ Path.validate! path, false
19
+
20
+ if Path.absolute?(path)
21
+ Path.normalize path
22
+ elsif path.empty?
23
+ self
24
+ else
25
+ Path.normalize "#{self}#{'/' unless self == '/'}#{path}"
26
+ end
27
+ end
28
+
29
+ def parent
30
+ self + '..'
31
+ end
32
+
33
+ def probably_dir?
34
+ !!@probably_dir
35
+ end
36
+
37
+ def name
38
+ unless @name
39
+ root = self[0..0]
40
+ @name ||= split('/').last || root
41
+ end
42
+ @name
43
+ end
44
+
45
+ class << self
46
+ def absolute? path
47
+ path =~ /^[\/~\/]|^\.$|^\.\//
48
+ end
49
+
50
+ def valid? path, forbid_relative = true, &block
51
+ result, err = if forbid_relative and !absolute?(path)
52
+ [false, "path must be started with '/', or '.'"]
53
+ elsif path =~ /.+\/~$|.+\/$|\/\.$/
54
+ [false, "path can't be ended with '/', '/~', or '/.'"]
55
+ elsif path =~ /\/\/|\/~\/|\/\.\//
56
+ [false, "path can't include '/./', '/~/', '//' combinations!"]
57
+ # elsif path =~ /.+[~]|\/\.\//
58
+ # [false, "'~', or '.' can be present only at the begining of string"]
59
+ else
60
+ [true, nil]
61
+ end
62
+
63
+ block.call err if block and !result and err
64
+ result
65
+ end
66
+
67
+ def normalize path
68
+ path, probably_dir = normalize_to_string path
69
+ unless path
70
+ nil
71
+ else
72
+ Path.new(path, skip_normalization: true, probably_dir: probably_dir)
73
+ end
74
+ end
75
+
76
+ def validate! path, forbid_relative = true
77
+ valid?(path, forbid_relative){|error| raise "invalid path '#{path}' (#{error})!"}
78
+ end
79
+
80
+ def normalize_to_string path
81
+ root = path[0..0]
82
+ result, probably_dir = [], false
83
+
84
+ parts = path.split('/')[1..-1]
85
+ if parts
86
+ parts.each do |part|
87
+ if part == '..' and (root != '.' or (root == '.' and result.size > 0))
88
+ return nil, false unless result.size > 0
89
+ result.pop
90
+ probably_dir ||= true
91
+ else
92
+ result << part
93
+ probably_dir &&= false
94
+ end
95
+ end
96
+ end
97
+ normalized_path = result.join('/')
98
+
99
+ probably_dir ||= true if normalized_path.empty?
100
+
101
+ return "#{root}#{'/' unless root == '/' or normalized_path.empty?}#{normalized_path}", probably_dir
102
+ end
103
+ end
104
+
105
+ # protected
106
+ # def delete_dir_mark
107
+ # path = path.to_s.sub(%r{/$}, '')
108
+ # end
109
+ #
110
+ #
111
+ # def root_path? path
112
+ # path =~ /^[#{ROOT_SYMBOLS}]$/
113
+ # end
114
+ #
115
+ # def split_path path
116
+ # path.split(/#{ROOT_SYMBOLS}/)
117
+ # end
118
+ #
119
+ # def dir_mark? path
120
+ # path =~ %r{/$}
121
+ # end
122
+ end
123
+ end
@@ -0,0 +1,3 @@
1
+ module Vfs
2
+ VERSION = "0.0.1"
3
+ end
data/lib/vfs/vfs.rb ADDED
@@ -0,0 +1,38 @@
1
+ module Vfs
2
+ class << self
3
+ def default_driver
4
+ ::Vfs::Drivers::Local.new
5
+ end
6
+
7
+ def to_entry
8
+ '/'.to_entry
9
+ end
10
+
11
+ def to_file
12
+ to_entry.file
13
+ end
14
+
15
+ def to_dir
16
+ to_entry.dir
17
+ end
18
+
19
+ # def [] path
20
+ # to_entry[path]
21
+ # end
22
+ # alias_method :/, :[]
23
+
24
+ %w(
25
+ entry dir file
26
+ entries dirs files
27
+ [] /
28
+ tmp
29
+ ).each do |m|
30
+ script = <<-RUBY
31
+ def #{m} *a, &b
32
+ to_entry.#{m} *a, &b
33
+ end
34
+ RUBY
35
+ eval script, binding, __FILE__, __LINE__
36
+ end
37
+ end
38
+ end
data/old/hash_fs.rb ADDED
@@ -0,0 +1,216 @@
1
+ #
2
+ # Very dirty and inefficient In Memory File System, mainly for tests.
3
+ #
4
+ module Vfs
5
+ module Drivers
6
+ class HashFs < Hash
7
+ def initialize
8
+ super
9
+ self['/'] = {dir: true}
10
+ end
11
+
12
+
13
+ def open &block
14
+ block.call self
15
+ end
16
+
17
+ #
18
+ # Attributes
19
+ #
20
+ def attributes path
21
+ base, name = split_path path
22
+
23
+ # if path == '/'
24
+ # return {dir: true, file: false}
25
+ # end
26
+ #
27
+ stat = cd(base)[name]
28
+ attrs = {}
29
+ attrs[:file] = !!stat[:file]
30
+ attrs[:dir] = !!stat[:dir]
31
+ attrs
32
+ rescue Exception
33
+ {}
34
+ end
35
+
36
+ def set_attributes path, attrs
37
+ raise 'not supported'
38
+ end
39
+
40
+
41
+ #
42
+ # File
43
+ #
44
+ def read_file path, &block
45
+ base, name = split_path path
46
+ assert cd(base)[name], :include?, :file
47
+ block.call cd(base)[name][:content]
48
+ end
49
+
50
+ def write_file path, append, &block
51
+ base, name = split_path path
52
+
53
+ os = if append
54
+ file = cd(base)[name]
55
+ file ? file[:content] : ''
56
+ else
57
+ assert_not cd(base), :include?, name
58
+ ''
59
+ end
60
+ writer = -> buff {os << buff}
61
+ block.call writer
62
+
63
+ cd(base)[name] = {file: true, content: os}
64
+ end
65
+
66
+ def delete_file path
67
+ base, name = split_path path
68
+ assert cd(base)[name], :include?, :file
69
+ cd(base).delete name
70
+ end
71
+
72
+ # def move_file path
73
+ # raise 'not supported'
74
+ # end
75
+
76
+
77
+ #
78
+ # Dir
79
+ #
80
+ def create_dir path
81
+ base, name = split_path path
82
+ assert_not cd(base), :include?, name
83
+ cd(base)[name] = {dir: true}
84
+ end
85
+
86
+ def delete_dir path
87
+ base, name = split_path path
88
+ assert cd(base)[name], :include?, :dir
89
+ # empty = true
90
+ # cd(base)[name].each do |key, value|
91
+ # empty = false if key.is_a? String
92
+ # end
93
+ # raise 'you are trying to delete not empty dir!' unless empty
94
+ cd(base).delete name
95
+ end
96
+
97
+ # def move_dir path
98
+ # raise 'not supported'
99
+ # end
100
+
101
+ def each_entry path, query, &block
102
+ raise "hash_fs not support :each_entry with query!" if query
103
+
104
+ base, name = split_path path
105
+ assert cd(base)[name], :include?, :dir
106
+ cd(base)[name].each do |relative_name, content|
107
+ next if relative_name.is_a? Symbol
108
+ if content[:dir]
109
+ block.call relative_name, :dir
110
+ else
111
+ block.call relative_name, :file
112
+ end
113
+ end
114
+ end
115
+
116
+ def efficient_dir_copy from, to, override
117
+ from.driver.open do |from_fs|
118
+ to.driver.open do |to_fs|
119
+ if from_fs == to_fs
120
+ for_spec_helper_effective_copy_used
121
+
122
+ _efficient_dir_copy from.path, to.path, override
123
+ true
124
+ else
125
+ false
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ def _efficient_dir_copy from_path, to_path, override
132
+ from_base, from_name = split_path from_path
133
+ assert cd(from_base)[from_name], :include?, :dir
134
+
135
+ to_base, to_name = split_path to_path
136
+ # assert_not cd(to_base), :include?, to_name
137
+
138
+ if cd(to_base).include? to_name
139
+ if cd(to_base)[to_name][:dir]
140
+ each_entry from_path, nil do |name, type|
141
+ if type == :dir
142
+ _efficient_dir_copy "#{from_path}/#{name}", "#{to_path}/#{name}", override
143
+ else
144
+ raise "file #{to_path}/#{name} already exist!" if cd(to_base)[to_name].include?(name) and !override
145
+ cd(to_base)[to_name][name] = cd(from_base)[from_name][name].clone
146
+ end
147
+ end
148
+ else
149
+ raise "can't copy dir #{from_path} to file #{to_path}!"
150
+ end
151
+ else
152
+ cd(to_base)[to_name] = {dir: true}
153
+ _efficient_dir_copy from_path, to_path, override
154
+ end
155
+ end
156
+ protected :_efficient_dir_copy
157
+ def for_spec_helper_effective_copy_used; end
158
+
159
+ # def upload_directory from_local_path, to_remote_path
160
+ # FileUtils.cp_r from_local_path, to_remote_path
161
+ # end
162
+ #
163
+ # def download_directory from_remote_path, to_local_path
164
+ # FileUtils.cp_r from_remote_path, to_local_path
165
+ # end
166
+
167
+
168
+ #
169
+ # Other
170
+ #
171
+ def local?; true end
172
+
173
+ def to_s; 'hash_fs' end
174
+
175
+ def tmp &block
176
+ tmp_dir = "/tmp_#{rand(10**6)}"
177
+ create_dir tmp_dir
178
+ if block
179
+ begin
180
+ block.call tmp_dir
181
+ ensure
182
+ delete_dir tmp_dir
183
+ end
184
+ else
185
+ tmp_dir
186
+ end
187
+ end
188
+
189
+ protected
190
+ def assert obj, method, arg
191
+ raise "#{obj} should #{method} #{arg}" unless obj.send method, arg
192
+ end
193
+
194
+ def assert_not obj, method, arg
195
+ raise "#{obj} should not #{method} #{arg}" if obj.send method, arg
196
+ end
197
+
198
+ def split_path path
199
+ parts = path[1..-1].split('/')
200
+ parts.unshift '/'
201
+ name = parts.pop
202
+ return parts, name
203
+ end
204
+
205
+ def cd parts
206
+ current = self
207
+ iterator = parts.clone
208
+ while iterator.first
209
+ current = current[iterator.first]
210
+ iterator.shift
211
+ end
212
+ current
213
+ end
214
+ end
215
+ end
216
+ end