nested_file 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ module NestedFile
2
+ class ConvertPath
3
+ include FromHash
4
+ attr_accessor :parent_dir, :mount_dir
5
+ # converts the directory relative to the mount point to an absolute parent path
6
+ def mount_to_parent(path)
7
+ File.join parent_dir, path
8
+ end
9
+ def parent_to_mount(path)
10
+ path.gsub("#{parent_dir}/","")
11
+ end
12
+ def mount_to_parent_if_relative(path)
13
+ if Pathname.new(path).absolute?
14
+ path
15
+ else
16
+ mount_to_parent(path)
17
+ end
18
+ end
19
+ end
20
+
21
+ class PutDir
22
+ include FromHash
23
+ attr_accessor :parent_dir, :mount_dir, :relative_dir
24
+
25
+ fattr(:convert_path) do
26
+ ConvertPath.new(parent_dir: parent_dir, mount_dir: mount_dir)
27
+ end
28
+ fattr(:relative_convert_path) do
29
+ ConvertPath.new(parent_dir: relative_dir||parent_dir, mount_dir: mount_dir)
30
+ end
31
+ extend Forwardable
32
+ def_delegators :convert_path, :mount_to_parent, :parent_to_mount
33
+
34
+ def contents(path)
35
+ log "contents for #{path}" do
36
+ parent_path = mount_to_parent(path)
37
+ res = Dir.entries(parent_path)
38
+ res.map { |x| File.basename(x) }
39
+ end
40
+ end
41
+ def file?(path)
42
+ FileTest.file? mount_to_parent(path)
43
+ end
44
+ def directory?(path)
45
+ FileTest.directory? mount_to_parent(path)
46
+ end
47
+ def read_file_inner(path)
48
+ body = File.read(mount_to_parent(path))
49
+ PutFile.new(raw_body: body, filename: mount_to_parent(path), convert_path: relative_convert_path).parsed_body
50
+ end
51
+ def read_file(path)
52
+ log "read file #{path}" do
53
+ read_file_inner path
54
+ end
55
+ end
56
+ def size(path)
57
+ log "size for #{path}" do
58
+ read_file_inner(path).size
59
+ end
60
+ end
61
+
62
+ module Raw
63
+ def raw_open(path,*args)
64
+ if args[0] == 'w'
65
+ File.new(mount_to_parent(path),'w')
66
+ else
67
+ nil
68
+ end
69
+ end
70
+ def raw_truncate(path,i,f)
71
+ f.truncate(i)
72
+ end
73
+ def raw_close(*args)
74
+ args.last.close
75
+ end
76
+ def raw_write(path,offset,sz,buf,file=nil)
77
+ PutFile.new(raw_body: buf, filename: mount_to_parent(path), convert_path: relative_convert_path).write_all! file
78
+ buf.length
79
+ end
80
+ end
81
+ include Raw
82
+
83
+ def can_write?(path)
84
+ true
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,43 @@
1
+ module NestedFile
2
+ class PutFile
3
+ include FromHash
4
+ attr_accessor :raw_body, :filename, :convert_path
5
+
6
+ fattr(:parsed_body) do
7
+ res = raw_body.gsub(/<file (.+?)>.*?<\/file>/m) do
8
+ f = $1
9
+ full = convert_path.mount_to_parent_if_relative(f)
10
+ FileSection::Read.new(file_to_insert: f, full_file_to_insert: full).to_s
11
+ end
12
+ res.gsub(/<files (.+?)>.*?<\/files>/m) do
13
+ f = $1
14
+ full = convert_path.mount_to_parent_if_relative(f)
15
+ FileGroup.new(file_glob: f, full_glob: full, convert_path: convert_path).to_s
16
+ end
17
+ end
18
+
19
+ def write_subs!
20
+ raw_body.scan(/<file (.+?)>(.*?)<\/file>/m) do |m|
21
+ sub_file, sub_body = *m
22
+ #ff = File.expand_path(sub_file,File.dirname(filename))
23
+ full = convert_path.mount_to_parent_if_relative(sub_file)
24
+ FileSection::Write.new(parent_body: sub_body, full_file_to_insert: full).write!
25
+ end
26
+ end
27
+ def write_self!(file=nil)
28
+ res = raw_body.gsub(/<file (.+?)>(.*?)<\/file>/m) do
29
+ "<file #{$1}>\n</file>"
30
+ end
31
+
32
+ if file
33
+ file.write res
34
+ else
35
+ File.create filename, res
36
+ end
37
+ end
38
+ def write_all!(file=nil)
39
+ write_subs!
40
+ write_self!(file)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ module NestedFile
2
+ def self.root
3
+ res = File.expand_path(File.dirname(__FILE__))+"/../.."
4
+ File.expand_path(res)
5
+ end
6
+ end
7
+
8
+ def log(str)
9
+ res = nil
10
+ if block_given?
11
+ res = yield
12
+ str = "#{str} res: #{res}"
13
+ end
14
+ # puts str
15
+ File.append "/code/orig/nested_file/debug.log","#{str}\n"
16
+ res
17
+ end
18
+
19
+ File.create "/code/orig/nested_file/debug.log","Starting at #{Time.now}\n"
20
+
21
+ # class String
22
+ # def gsub_safe(reg,str,&b)
23
+ # res = gsub(reg,str,&b)
24
+ # c = caller.join("\n")
25
+ # raise "didn't change, gsub #{self} with #{reg}, replace with #{str}\n#{c}" if res == self
26
+ # res
27
+ # end
28
+ # end
@@ -0,0 +1,110 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: nested_file 0.0.1 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "nested_file"
9
+ s.version = "0.0.1"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Mike Harris"]
14
+ s.date = "2016-05-17"
15
+ s.description = "nested_file"
16
+ s.email = "mharris717@gmail.com"
17
+ s.executables = ["nested_file"]
18
+ s.extra_rdoc_files = [
19
+ "LICENSE.txt",
20
+ "README.rdoc"
21
+ ]
22
+ s.files = [
23
+ ".document",
24
+ ".rspec",
25
+ ".travis.yml",
26
+ "Gemfile",
27
+ "Gemfile.lock",
28
+ "Guardfile",
29
+ "LICENSE.txt",
30
+ "README.rdoc",
31
+ "Rakefile",
32
+ "VERSION",
33
+ "bin/nested_file",
34
+ "lib/nested_file.rb",
35
+ "lib/nested_file/file_group.rb",
36
+ "lib/nested_file/file_section.rb",
37
+ "lib/nested_file/file_tag.rb",
38
+ "lib/nested_file/put_dir.rb",
39
+ "lib/nested_file/put_file.rb",
40
+ "lib/nested_file/util.rb",
41
+ "nested_file.gemspec",
42
+ "spec/file_section_spec.rb",
43
+ "spec/nested_file_spec.rb",
44
+ "spec/parent_template/a.txt",
45
+ "spec/parent_template/include_others.txt",
46
+ "spec/parent_template/include_others_rel.txt",
47
+ "spec/parent_template/sub2/x.txt",
48
+ "spec/put_dir_spec.rb",
49
+ "spec/spec_helper.rb",
50
+ "tmp/.gitkeep",
51
+ "unmount_all_fuse.rb",
52
+ "util/green.gif",
53
+ "util/package.json",
54
+ "util/red.png",
55
+ "util/run_specs",
56
+ "util/watch.js",
57
+ "vol/spawn_mount.rb",
58
+ "vol/watch_cat.rb"
59
+ ]
60
+ s.homepage = "http://github.com/mharris717/nested_file"
61
+ s.licenses = ["MIT"]
62
+ s.rubygems_version = "2.5.1"
63
+ s.summary = "nested_file"
64
+
65
+ if s.respond_to? :specification_version then
66
+ s.specification_version = 4
67
+
68
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
69
+ s.add_runtime_dependency(%q<mharris_ext>, [">= 0"])
70
+ s.add_runtime_dependency(%q<rfusefs>, [">= 0"])
71
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
72
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
73
+ s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
74
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
75
+ s.add_development_dependency(%q<guard>, [">= 0"])
76
+ s.add_development_dependency(%q<guard-rspec>, [">= 0"])
77
+ s.add_development_dependency(%q<guard-spork>, [">= 0"])
78
+ s.add_development_dependency(%q<rb-fsevent>, ["~> 0.9"])
79
+ s.add_development_dependency(%q<lre>, [">= 0"])
80
+ s.add_development_dependency(%q<rr>, [">= 0"])
81
+ else
82
+ s.add_dependency(%q<mharris_ext>, [">= 0"])
83
+ s.add_dependency(%q<rfusefs>, [">= 0"])
84
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
85
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
86
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
87
+ s.add_dependency(%q<jeweler>, [">= 0"])
88
+ s.add_dependency(%q<guard>, [">= 0"])
89
+ s.add_dependency(%q<guard-rspec>, [">= 0"])
90
+ s.add_dependency(%q<guard-spork>, [">= 0"])
91
+ s.add_dependency(%q<rb-fsevent>, ["~> 0.9"])
92
+ s.add_dependency(%q<lre>, [">= 0"])
93
+ s.add_dependency(%q<rr>, [">= 0"])
94
+ end
95
+ else
96
+ s.add_dependency(%q<mharris_ext>, [">= 0"])
97
+ s.add_dependency(%q<rfusefs>, [">= 0"])
98
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
99
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
100
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
101
+ s.add_dependency(%q<jeweler>, [">= 0"])
102
+ s.add_dependency(%q<guard>, [">= 0"])
103
+ s.add_dependency(%q<guard-rspec>, [">= 0"])
104
+ s.add_dependency(%q<guard-spork>, [">= 0"])
105
+ s.add_dependency(%q<rb-fsevent>, ["~> 0.9"])
106
+ s.add_dependency(%q<lre>, [">= 0"])
107
+ s.add_dependency(%q<rr>, [">= 0"])
108
+ end
109
+ end
110
+
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "FileSection" do
4
+ include_context "file stub"
5
+
6
+ it 'smoke' do
7
+ file = "/a/b/c"
8
+ body = 'abc'
9
+ file_stub.add file,body
10
+ section = NestedFile::FileSection.new(full_file_to_insert: file, file_to_insert: file)
11
+ section.insert_body.should == body
12
+ section.to_s.should == "<file /a/b/c>\nabc\n</file>"
13
+ end
14
+
15
+ it 'smoke' do
16
+ file = "c.txt"
17
+ file_stub.add "/a/c.txt",'abc'
18
+
19
+ section = NestedFile::FileSection.new(file_to_insert: file, full_file_to_insert: "/a/c.txt")
20
+ section.to_s.should == "<file c.txt>\nabc\n</file>"
21
+ end
22
+
23
+ it "reading file that doesn't exist" do
24
+ section = NestedFile::FileSection.new(full_file_to_insert: "a.txt", file_to_insert: nil)
25
+ section.insert_body.should == ''
26
+ end
27
+
28
+ it 'trimmed_body only trims 1 newline' do
29
+ section = NestedFile::FileSection::Write.new(parent_body: "\n\nabc\n")
30
+ section.trimmed_parent_body.should == "\nabc"
31
+ end
32
+ end
@@ -0,0 +1,249 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ def try_for_period(sec)
4
+ start = Time.now
5
+ while (Time.now-start) < sec
6
+ begin
7
+ return yield
8
+ rescue => exp
9
+ #puts "failed, elapsed #{Time.now-start}"
10
+ sleep(0.05)
11
+ end
12
+ end
13
+ raise 'reached end'
14
+ yield
15
+ end
16
+
17
+ def print_child_file_changes
18
+ puts "print_child_file_changes"
19
+ STDIN.gets
20
+ before_files = Dir["#{child_dir}/**/*.txt"]
21
+ yield
22
+ after_files = Dir["#{child_dir}/**/*.txt"]
23
+ both_files = (before_files+after_files).uniq
24
+
25
+ puts "#{both_files} total files"
26
+ both_files.each do |file|
27
+ if [before_files,after_files].any? { |fs| !fs.include?(file) }
28
+ puts "#{file} #{before_files.include?(file)}/#{after_files.include?(file)}"
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "NestedFile" do
34
+ let(:parent_dir) { Dir.mktmpdir("parent") }
35
+ let(:child_dir) { Dir.mktmpdir("child") }
36
+
37
+ def fork_mount
38
+ File.create "#{parent_dir}/zzz.txt","hello"
39
+ child_dir
40
+
41
+ pid = fork do
42
+ cmd = "bundle exec ruby ./bin/nested_file #{parent_dir} #{child_dir}"
43
+ exec cmd
44
+ end
45
+
46
+ sleep 0.05
47
+ try_for_period(2) do
48
+ File.read("#{child_dir}/zzz.txt")
49
+ end
50
+
51
+ mount_name = ec("mount", silent: true).scan(/^(\S+)\s.*#{child_dir}/).first.first
52
+ {pid: pid, mount_name: mount_name}
53
+ end
54
+
55
+ def create_parent_file(path,str)
56
+ try_for_period(2) do
57
+ File.create "#{parent_dir}/#{path}",str
58
+ end
59
+ end
60
+
61
+ def create_child_file(path,str)
62
+ try_for_period(2) do
63
+ File.create "#{child_dir}/#{path}",str
64
+ end
65
+ end
66
+
67
+ before(:all) do
68
+ @fork_data = fork_mount
69
+ end
70
+ after(:all) do
71
+ if @fork_data
72
+ Process.kill "KILL",@fork_data[:pid]
73
+ ec "umount #{@fork_data[:mount_name]}", silent: true
74
+ end
75
+ end
76
+
77
+ before(:each) do
78
+ `rm -rf #{parent_dir}/*`
79
+ Dir["spec/parent_template/*"].each do |f|
80
+ `cp -r #{f} #{parent_dir}`
81
+ end
82
+
83
+ Dir["#{parent_dir}/**/*.txt"].each do |file|
84
+ body = File.read(file).gsub("{{NF_ROOT}}",NestedFile.root).gsub("{{NF_PARENT_DIR}}",parent_dir)
85
+ File.create file, body
86
+ end
87
+ end
88
+
89
+ describe "basic reads" do
90
+ it 'read from mounted fs' do
91
+ str = File.read "#{child_dir}/a.txt"
92
+ str.should == "hello"
93
+ end
94
+
95
+ it 'read subs in file contents - full path' do
96
+ str = File.read "#{child_dir}/include_others.txt"
97
+ str.should == "<file #{parent_dir}/a.txt>\nhello\n</file>"
98
+ end
99
+
100
+ it 'read subs in file contents - relative_path' do
101
+ str = File.read "#{child_dir}/include_others_rel.txt"
102
+ str.should == "<file a.txt>\nhello\n</file>"
103
+ end
104
+
105
+ it 'ls should work in subs' do
106
+ Dir["#{child_dir}/sub2/*"].should == ["#{child_dir}/sub2/x.txt"]
107
+ end
108
+ end
109
+
110
+ describe "can use glob in file desc" do
111
+ before do
112
+ create_parent_file "sub/a.txt","abc"
113
+ create_parent_file "sub/b.txt","xyz"
114
+ create_parent_file "sub_all.txt","<files sub/*.txt></files>"
115
+ end
116
+
117
+ it 'shows group' do
118
+ exp = ['<files sub/*.txt>']
119
+ exp += ['<file sub/a.txt>','abc','</file>']
120
+ exp += ['<file sub/b.txt>','xyz','</file>']
121
+ exp << "</files>"
122
+ File.read("#{child_dir}/sub_all.txt").should == exp.join("\n")
123
+ end
124
+ end
125
+
126
+ describe "nested body not saved to parent" do
127
+ before do
128
+ create_child_file "d.txt","<file e.txt>data</file>"
129
+ end
130
+ it 'e is data' do
131
+ File.read("#{parent_dir}/e.txt").should == "data"
132
+ end
133
+ it "d.txt doesn't have body" do
134
+ File.read("#{parent_dir}/d.txt").should == "<file e.txt>\n</file>"
135
+ end
136
+ end
137
+
138
+
139
+ describe 'saving file with sections writes to other files' do
140
+ before(:each) do
141
+ body = "<file c.txt>\nI was here\n</file>"
142
+ create_child_file "b.txt",body
143
+ end
144
+
145
+ it 'exists' do
146
+ FileTest.should be_exist("#{parent_dir}/b.txt")
147
+ FileTest.should be_exist("#{child_dir}/b.txt")
148
+ FileTest.should be_exist("#{parent_dir}/c.txt")
149
+ FileTest.should be_exist("#{child_dir}/c.txt")
150
+ end
151
+
152
+ it 'c.txt has written text' do
153
+ File.read("#{parent_dir}/c.txt").should == "I was here"
154
+ end
155
+ end
156
+
157
+ describe 'saving file with sections writes to other files - relative path' do
158
+ before(:each) do
159
+ body = "<file c.txt>\nI was here\n</file>"
160
+ create_child_file "b.txt", body
161
+ end
162
+
163
+ it 'exists' do
164
+ FileTest.should be_exist("#{parent_dir}/b.txt")
165
+ FileTest.should be_exist("#{child_dir}/b.txt")
166
+ FileTest.should be_exist("#{parent_dir}/c.txt")
167
+ FileTest.should be_exist("#{child_dir}/c.txt")
168
+ end
169
+
170
+ it 'c.txt has written text' do
171
+ File.read("#{parent_dir}/c.txt").should == "I was here"
172
+ end
173
+
174
+ end
175
+
176
+ describe 'saving file with sections writes to other files - save to sub' do
177
+ before(:each) do
178
+ body = "<file sub/z.txt>\nI was here\n</file>"
179
+ create_child_file "b.txt", body
180
+ end
181
+
182
+ it 'z.txt has written text' do
183
+ File.read("#{parent_dir}/sub/z.txt").should == "I was here"
184
+ end
185
+ end
186
+
187
+ # this test probably useless now
188
+ describe 'saving file with sections writes to other files - save to parent' do
189
+ before(:each) do
190
+ body = "<file p.txt>\nI was here\n</file>"
191
+ create_child_file "sub/b.txt", body
192
+ end
193
+
194
+ it 'z.txt has written text' do
195
+ File.read("#{parent_dir}/p.txt").should == "I was here"
196
+ end
197
+ end
198
+
199
+ describe 'modifying file referenced elsewhere updates other file' do
200
+ def exp_body(body=nil)
201
+ if body
202
+ "<file #{parent_dir}/a.txt>\n#{body}\n</file>"
203
+ else
204
+ "<file #{parent_dir}/a.txt>\n</file>"
205
+ end
206
+ end
207
+ def parent_body
208
+ File.read("#{parent_dir}/include_others.txt")
209
+ end
210
+ def child_body
211
+ File.read("#{child_dir}/include_others.txt")
212
+ end
213
+
214
+ it 'writing to parent - longer string - include_others.txt has written text' do
215
+ create_parent_file "a.txt", "Hello There"
216
+ parent_body.should == exp_body
217
+ child_body.should == exp_body('Hello There')
218
+ end
219
+
220
+ it 'writing to child - longer string - include_others.txt has written text' do
221
+ create_child_file "a.txt", "Hello There"
222
+ parent_body.should == exp_body
223
+ child_body.should == exp_body('Hello There')
224
+ end
225
+
226
+ it 'writing to parent - shorter string - include_others.txt has written text' do
227
+ create_parent_file "a.txt", "bb"
228
+ parent_body.should == exp_body
229
+ child_body.should == exp_body('bb')
230
+ end
231
+
232
+ it 'writing to child - shorter string - include_others.txt has written text' do
233
+ create_child_file "a.txt", "bb"
234
+ parent_body.should == exp_body
235
+ child_body.should == exp_body('bb')
236
+ end
237
+ end
238
+
239
+ describe "don't overwrite existing" do
240
+ before do
241
+ create_parent_file "exist.txt","Hello"
242
+ create_child_file "summary.txt","<file exist.txt></file>"
243
+ end
244
+
245
+ it 'leaves exist.txt alone' do
246
+ File.read("#{parent_dir}/exist.txt").should == 'Hello'
247
+ end
248
+ end
249
+ end