memfs 1.0.0 → 2.0.0
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.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +19 -0
- data/.github/workflows/ci.yml +64 -0
- data/.rspec +1 -1
- data/.rubocop.yml +98 -0
- data/CHANGELOG.md +30 -10
- data/Gemfile +19 -0
- data/Guardfile +5 -3
- data/README.md +3 -3
- data/Rakefile +4 -2
- data/bin/_guard-core +16 -0
- data/bin/coverage_summary +51 -0
- data/bin/guard +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/bin/rubocop +16 -0
- data/lib/memfs/dir.rb +82 -17
- data/lib/memfs/fake/directory.rb +31 -6
- data/lib/memfs/fake/entry.rb +41 -25
- data/lib/memfs/fake/file/content.rb +6 -3
- data/lib/memfs/fake/file.rb +2 -0
- data/lib/memfs/fake/symlink.rb +2 -0
- data/lib/memfs/file/stat.rb +20 -13
- data/lib/memfs/file.rb +74 -66
- data/lib/memfs/file_system.rb +14 -9
- data/lib/memfs/filesystem_access.rb +2 -0
- data/lib/memfs/io.rb +48 -54
- data/lib/memfs/version.rb +3 -1
- data/lib/memfs.rb +83 -3
- data/memfs.gemspec +0 -17
- data/spec/fileutils_spec.rb +64 -41
- data/spec/memfs/dir_spec.rb +155 -18
- data/spec/memfs/fake/directory_spec.rb +3 -3
- data/spec/memfs/fake/entry_spec.rb +11 -5
- data/spec/memfs/fake/symlink_spec.rb +1 -1
- data/spec/memfs/file/stat_spec.rb +27 -15
- data/spec/memfs/file_spec.rb +135 -51
- data/spec/memfs/file_system_spec.rb +15 -15
- data/spec/memfs_spec.rb +29 -1
- data/spec/spec_helper.rb +19 -4
- metadata +17 -151
- data/.hound.yml +0 -2
- data/.rubocop.yml +0 -1
- data/.ruby-style.yml +0 -335
- data/.travis.yml +0 -9
data/spec/fileutils_spec.rb
CHANGED
|
@@ -4,7 +4,7 @@ require 'spec_helper'
|
|
|
4
4
|
|
|
5
5
|
RSpec.describe FileUtils do
|
|
6
6
|
before :each do
|
|
7
|
-
MemFs::File.umask(
|
|
7
|
+
MemFs::File.umask(0o020)
|
|
8
8
|
MemFs.activate!
|
|
9
9
|
|
|
10
10
|
described_class.mkdir '/test'
|
|
@@ -17,11 +17,17 @@ RSpec.describe FileUtils do
|
|
|
17
17
|
describe '.cd' do
|
|
18
18
|
it 'changes the current working directory' do
|
|
19
19
|
described_class.cd '/test'
|
|
20
|
-
expect(described_class.pwd).to eq('/test')
|
|
20
|
+
expect(described_class.pwd).to eq(expected_path('/test'))
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
if MemFs.ruby_version_gte?('2.6')
|
|
24
|
+
it 'returns 0' do
|
|
25
|
+
expect(described_class.cd('/test')).to eq 0
|
|
26
|
+
end
|
|
27
|
+
else
|
|
28
|
+
it 'returns nil' do
|
|
29
|
+
expect(described_class.cd('/test')).to be_nil
|
|
30
|
+
end
|
|
25
31
|
end
|
|
26
32
|
|
|
27
33
|
it "raises an error when the given path doesn't exist" do
|
|
@@ -36,7 +42,7 @@ RSpec.describe FileUtils do
|
|
|
36
42
|
context 'when called with a block' do
|
|
37
43
|
it 'changes current working directory for the block execution' do
|
|
38
44
|
described_class.cd '/test' do
|
|
39
|
-
expect(described_class.pwd).to eq('/test')
|
|
45
|
+
expect(described_class.pwd).to eq(expected_path('/test'))
|
|
40
46
|
end
|
|
41
47
|
end
|
|
42
48
|
|
|
@@ -53,7 +59,7 @@ RSpec.describe FileUtils do
|
|
|
53
59
|
|
|
54
60
|
it 'changes directory to the last target of the link chain' do
|
|
55
61
|
described_class.cd('/test-link')
|
|
56
|
-
expect(described_class.pwd).to eq('/test')
|
|
62
|
+
expect(described_class.pwd).to eq(expected_path('/test'))
|
|
57
63
|
end
|
|
58
64
|
|
|
59
65
|
it "raises an error if the last target of the link chain doesn't exist" do
|
|
@@ -65,24 +71,24 @@ RSpec.describe FileUtils do
|
|
|
65
71
|
describe '.chmod' do
|
|
66
72
|
it 'changes permission bits on the named file to the bit pattern represented by mode' do
|
|
67
73
|
described_class.touch '/test-file'
|
|
68
|
-
described_class.chmod
|
|
69
|
-
expect(File.stat('/test-file').mode).to eq(
|
|
74
|
+
described_class.chmod 0o777, '/test-file'
|
|
75
|
+
expect(File.stat('/test-file').mode).to eq(0o100777)
|
|
70
76
|
end
|
|
71
77
|
|
|
72
78
|
it 'changes permission bits on the named files (in list) to the bit pattern represented by mode' do
|
|
73
79
|
described_class.touch ['/test-file', '/test-file2']
|
|
74
|
-
described_class.chmod
|
|
75
|
-
expect(File.stat('/test-file2').mode).to eq(
|
|
80
|
+
described_class.chmod 0o777, ['/test-file', '/test-file2']
|
|
81
|
+
expect(File.stat('/test-file2').mode).to eq(0o100777)
|
|
76
82
|
end
|
|
77
83
|
|
|
78
84
|
it 'returns an array containing the file names' do
|
|
79
85
|
file_names = %w[/test-file /test-file2]
|
|
80
86
|
described_class.touch file_names
|
|
81
|
-
expect(described_class.chmod(
|
|
87
|
+
expect(described_class.chmod(0o777, file_names)).to eq(file_names)
|
|
82
88
|
end
|
|
83
89
|
|
|
84
90
|
it 'raises an error if an entry does not exist' do
|
|
85
|
-
expect { described_class.chmod(
|
|
91
|
+
expect { described_class.chmod(0o777, '/test-file') }.to raise_error(Errno::ENOENT)
|
|
86
92
|
end
|
|
87
93
|
|
|
88
94
|
context 'when the named file is a symlink' do
|
|
@@ -93,13 +99,13 @@ RSpec.describe FileUtils do
|
|
|
93
99
|
|
|
94
100
|
context 'when File responds to lchmod' do
|
|
95
101
|
it 'changes the mode on the link' do
|
|
96
|
-
described_class.chmod(
|
|
97
|
-
expect(File.lstat('/test-link').mode).to eq(
|
|
102
|
+
described_class.chmod(0o777, '/test-link')
|
|
103
|
+
expect(File.lstat('/test-link').mode).to eq(0o100777)
|
|
98
104
|
end
|
|
99
105
|
|
|
100
106
|
it "doesn't change the mode of the link's target" do
|
|
101
107
|
mode = File.lstat('/test-file').mode
|
|
102
|
-
described_class.chmod(
|
|
108
|
+
described_class.chmod(0o777, '/test-link')
|
|
103
109
|
expect(File.lstat('/test-file').mode).to eq(mode)
|
|
104
110
|
end
|
|
105
111
|
end
|
|
@@ -109,7 +115,7 @@ RSpec.describe FileUtils do
|
|
|
109
115
|
allow_any_instance_of(described_class::Entry_).to \
|
|
110
116
|
receive_messages(have_lchmod?: false)
|
|
111
117
|
mode = File.lstat('/test-link').mode
|
|
112
|
-
described_class.chmod(
|
|
118
|
+
described_class.chmod(0o777, '/test-link')
|
|
113
119
|
expect(File.lstat('/test-link').mode).to eq(mode)
|
|
114
120
|
end
|
|
115
121
|
end
|
|
@@ -122,18 +128,18 @@ RSpec.describe FileUtils do
|
|
|
122
128
|
end
|
|
123
129
|
|
|
124
130
|
it 'changes the permission bits on the named entry' do
|
|
125
|
-
described_class.chmod_R(
|
|
126
|
-
expect(File.stat('/test').mode).to eq(
|
|
131
|
+
described_class.chmod_R(0o777, '/test')
|
|
132
|
+
expect(File.stat('/test').mode).to eq(0o100777)
|
|
127
133
|
end
|
|
128
134
|
|
|
129
135
|
it 'changes the permission bits on any sub-directory of the named entry' do
|
|
130
|
-
described_class.chmod_R(
|
|
131
|
-
expect(File.stat('/test').mode).to eq(
|
|
136
|
+
described_class.chmod_R(0o777, '/')
|
|
137
|
+
expect(File.stat('/test').mode).to eq(0o100777)
|
|
132
138
|
end
|
|
133
139
|
|
|
134
140
|
it 'changes the permission bits on any descendant file of the named entry' do
|
|
135
|
-
described_class.chmod_R(
|
|
136
|
-
expect(File.stat('/test/test-file').mode).to eq(
|
|
141
|
+
described_class.chmod_R(0o777, '/')
|
|
142
|
+
expect(File.stat('/test/test-file').mode).to eq(0o100777)
|
|
137
143
|
end
|
|
138
144
|
end
|
|
139
145
|
|
|
@@ -311,7 +317,7 @@ RSpec.describe FileUtils do
|
|
|
311
317
|
before :each do
|
|
312
318
|
described_class.touch('/test-file')
|
|
313
319
|
described_class.chown(1042, 1042, '/test-file')
|
|
314
|
-
described_class.chmod(
|
|
320
|
+
described_class.chmod(0o777, '/test-file')
|
|
315
321
|
_fs.find('/test-file').mtime = time
|
|
316
322
|
described_class.copy_entry('/test-file', '/test-copy', true)
|
|
317
323
|
end
|
|
@@ -325,7 +331,7 @@ RSpec.describe FileUtils do
|
|
|
325
331
|
end
|
|
326
332
|
|
|
327
333
|
it 'preserves permissions' do
|
|
328
|
-
expect(File.stat('/test-copy').mode).to eq(
|
|
334
|
+
expect(File.stat('/test-copy').mode).to eq(0o100777)
|
|
329
335
|
end
|
|
330
336
|
|
|
331
337
|
it 'preserves modified time' do
|
|
@@ -468,8 +474,8 @@ RSpec.describe FileUtils do
|
|
|
468
474
|
|
|
469
475
|
context 'when +:mode+ is set' do
|
|
470
476
|
it 'changes the permission mode to +mode+' do
|
|
471
|
-
expect(File).to receive(:chmod).with(
|
|
472
|
-
described_class.install('/test-file', '/test-file2', mode:
|
|
477
|
+
expect(File).to receive(:chmod).with(0o777, '/test-file2')
|
|
478
|
+
described_class.install('/test-file', '/test-file2', mode: 0o777)
|
|
473
479
|
end
|
|
474
480
|
end
|
|
475
481
|
|
|
@@ -656,9 +662,9 @@ RSpec.describe FileUtils do
|
|
|
656
662
|
context 'when passing options' do
|
|
657
663
|
context 'when passing mode parameter' do
|
|
658
664
|
it 'creates directory with specified permissions' do
|
|
659
|
-
described_class.mkdir('/test-dir', mode:
|
|
665
|
+
described_class.mkdir('/test-dir', mode: 0o654)
|
|
660
666
|
expect(File.exist?('/test-dir')).to be true
|
|
661
|
-
expect(File.stat('/test-dir').mode).to eq(
|
|
667
|
+
expect(File.stat('/test-dir').mode).to eq(0o100654)
|
|
662
668
|
end
|
|
663
669
|
end
|
|
664
670
|
|
|
@@ -698,9 +704,9 @@ RSpec.describe FileUtils do
|
|
|
698
704
|
context 'when passing options' do
|
|
699
705
|
context 'when passing mode parameter' do
|
|
700
706
|
it 'creates directory with specified permissions' do
|
|
701
|
-
described_class.mkdir_p('/test-dir', mode:
|
|
707
|
+
described_class.mkdir_p('/test-dir', mode: 0o654)
|
|
702
708
|
expect(File.exist?('/test-dir')).to be true
|
|
703
|
-
expect(File.stat('/test-dir').mode).to eq(
|
|
709
|
+
expect(File.stat('/test-dir').mode).to eq(0o100654)
|
|
704
710
|
end
|
|
705
711
|
end
|
|
706
712
|
|
|
@@ -759,7 +765,7 @@ RSpec.describe FileUtils do
|
|
|
759
765
|
describe '.pwd' do
|
|
760
766
|
it 'returns the name of the current directory' do
|
|
761
767
|
described_class.cd '/test'
|
|
762
|
-
expect(described_class.pwd).to eq('/test')
|
|
768
|
+
expect(described_class.pwd).to eq(expected_path('/test'))
|
|
763
769
|
end
|
|
764
770
|
end
|
|
765
771
|
|
|
@@ -809,28 +815,28 @@ RSpec.describe FileUtils do
|
|
|
809
815
|
end
|
|
810
816
|
|
|
811
817
|
it 'removes a file system entry +path+' do
|
|
812
|
-
described_class.chmod(
|
|
818
|
+
described_class.chmod(0o755, '/')
|
|
813
819
|
described_class.remove_entry_secure('/test-dir')
|
|
814
820
|
expect(Dir.exist?('/test-dir')).to be false
|
|
815
821
|
end
|
|
816
822
|
|
|
817
823
|
context 'when +path+ is a directory' do
|
|
818
824
|
it 'removes it recursively' do
|
|
819
|
-
described_class.chmod(
|
|
825
|
+
described_class.chmod(0o755, '/')
|
|
820
826
|
described_class.remove_entry_secure('/test-dir')
|
|
821
827
|
expect(Dir.exist?('/test-dir/test-sub-dir')).to be false
|
|
822
828
|
end
|
|
823
829
|
|
|
824
830
|
context 'and is word writable' do
|
|
825
831
|
it 'calls chown(2) on it' do
|
|
826
|
-
described_class.chmod(
|
|
832
|
+
described_class.chmod(0o1777, '/')
|
|
827
833
|
directory = _fs.find('/test-dir')
|
|
828
834
|
expect(directory).to receive(:uid=).at_least(:once)
|
|
829
835
|
described_class.remove_entry_secure('/test-dir')
|
|
830
836
|
end
|
|
831
837
|
|
|
832
838
|
it 'calls chmod(2) on all sub directories' do
|
|
833
|
-
described_class.chmod(
|
|
839
|
+
described_class.chmod(0o1777, '/')
|
|
834
840
|
directory = _fs.find('/test-dir')
|
|
835
841
|
expect(directory).to receive(:mode=).at_least(:once)
|
|
836
842
|
described_class.remove_entry_secure('/test-dir')
|
|
@@ -947,13 +953,30 @@ RSpec.describe FileUtils do
|
|
|
947
953
|
described_class.touch('/test-dir/test-file')
|
|
948
954
|
end
|
|
949
955
|
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
956
|
+
if RUBY_VERSION >= '2.5.0'
|
|
957
|
+
it 'raises an error' do
|
|
958
|
+
expect { described_class.rmdir('/test-dir') }
|
|
959
|
+
.to raise_error(Errno::ENOTEMPTY)
|
|
960
|
+
end
|
|
953
961
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
962
|
+
it 'doesn’t remove the directory' do
|
|
963
|
+
begin
|
|
964
|
+
described_class.rmdir('/test-dir')
|
|
965
|
+
rescue Errno::ENOTEMPTY
|
|
966
|
+
# noop
|
|
967
|
+
end
|
|
968
|
+
|
|
969
|
+
expect(Dir.exist?('/test-dir')).to be true
|
|
970
|
+
end
|
|
971
|
+
else
|
|
972
|
+
it 'ignores errors' do
|
|
973
|
+
expect { described_class.rmdir('/test-dir') }.not_to raise_error
|
|
974
|
+
end
|
|
975
|
+
|
|
976
|
+
it 'doesn’t remove the directory' do
|
|
977
|
+
described_class.rmdir('/test-dir')
|
|
978
|
+
expect(Dir.exist?('/test-dir')).to be true
|
|
979
|
+
end
|
|
957
980
|
end
|
|
958
981
|
end
|
|
959
982
|
end
|
data/spec/memfs/dir_spec.rb
CHANGED
|
@@ -13,13 +13,13 @@ module MemFs
|
|
|
13
13
|
describe '[]' do
|
|
14
14
|
context 'when a string is given' do
|
|
15
15
|
it 'acts like calling glob' do
|
|
16
|
-
expect(described_class['/*']).to eq
|
|
16
|
+
expect(described_class['/*']).to eq [expected_path('/tmp'), expected_path('/test')]
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
context 'when a list of strings is given' do
|
|
21
21
|
it 'acts like calling glob' do
|
|
22
|
-
expect(described_class['/tm*', '/te*']).to eq
|
|
22
|
+
expect(described_class['/tm*', '/te*']).to eq [expected_path('/tmp'), expected_path('/test')]
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -27,7 +27,7 @@ module MemFs
|
|
|
27
27
|
describe '.chdir' do
|
|
28
28
|
it 'changes the current working directory' do
|
|
29
29
|
described_class.chdir '/test'
|
|
30
|
-
expect(described_class.getwd).to eq('/test')
|
|
30
|
+
expect(described_class.getwd).to eq(expected_path('/test'))
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
it 'returns zero' do
|
|
@@ -41,7 +41,7 @@ module MemFs
|
|
|
41
41
|
context 'when a block is given' do
|
|
42
42
|
it 'changes current working directory for the block' do
|
|
43
43
|
described_class.chdir '/test' do
|
|
44
|
-
expect(described_class.pwd).to eq('/test')
|
|
44
|
+
expect(described_class.pwd).to eq(expected_path('/test'))
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -54,6 +54,22 @@ module MemFs
|
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
if MemFs.ruby_version_gte?('2.6')
|
|
58
|
+
describe '.children' do
|
|
59
|
+
it 'returns an array containing all of the filenames except for "." and ".." in this directory.' do
|
|
60
|
+
%w[/test/dir1 /test/dir2].each { |dir| described_class.mkdir dir }
|
|
61
|
+
_fs.touch '/test/file1', '/test/file2'
|
|
62
|
+
expect(described_class.children('/test')).to eq(%w[dir1 dir2 file1 file2])
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
describe '.children' do
|
|
67
|
+
it 'raises an error' do
|
|
68
|
+
expect { described_class.children('/test') }.to raise_error(NoMethodError)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
57
73
|
describe '.chroot' do
|
|
58
74
|
before { allow(Process).to receive_messages(uid: 0) }
|
|
59
75
|
|
|
@@ -96,6 +112,38 @@ module MemFs
|
|
|
96
112
|
it_behaves_like 'aliased method', :delete, :rmdir
|
|
97
113
|
end
|
|
98
114
|
|
|
115
|
+
describe '.empty?' do
|
|
116
|
+
context 'when the given directory is empty' do
|
|
117
|
+
it 'returns true' do
|
|
118
|
+
expect(described_class.empty?('/test')).to be true
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context 'when the given directory is non-empty' do
|
|
123
|
+
before { Dir.mkdir('/test/sub-dir') }
|
|
124
|
+
|
|
125
|
+
it 'returns false' do
|
|
126
|
+
expect(described_class.empty?('/test')).to be false
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context 'when the given directory does not exist' do
|
|
131
|
+
it 'raises an exception' do
|
|
132
|
+
expect {
|
|
133
|
+
described_class.empty?('/nothing')
|
|
134
|
+
}.to raise_exception(Errno::ENOENT)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
context 'when the given entry is not a directory' do
|
|
139
|
+
before { _fs.touch '/test/file1' }
|
|
140
|
+
|
|
141
|
+
it 'returns false' do
|
|
142
|
+
expect(described_class.empty?('/test/file1')).to be false
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
99
147
|
describe '.entries' do
|
|
100
148
|
it 'returns an array containing all of the filenames in the given directory' do
|
|
101
149
|
%w[/test/dir1 /test/dir2].each { |dir| described_class.mkdir dir }
|
|
@@ -202,7 +250,8 @@ module MemFs
|
|
|
202
250
|
|
|
203
251
|
shared_examples 'returning matching filenames' do |pattern, filenames|
|
|
204
252
|
it "with #{pattern}" do
|
|
205
|
-
|
|
253
|
+
expected = filenames.map { |f| expected_path(f) }
|
|
254
|
+
expect(described_class.glob(pattern)).to eq expected
|
|
206
255
|
end
|
|
207
256
|
end
|
|
208
257
|
|
|
@@ -226,14 +275,14 @@ module MemFs
|
|
|
226
275
|
context 'when a flag is given' do
|
|
227
276
|
it 'uses it to compare filenames' do
|
|
228
277
|
expect(described_class.glob('/TEST*', File::FNM_CASEFOLD)).to eq \
|
|
229
|
-
|
|
278
|
+
[expected_path('/test0'), expected_path('/test1'), expected_path('/test2')]
|
|
230
279
|
end
|
|
231
280
|
end
|
|
232
281
|
|
|
233
282
|
context 'when a block is given' do
|
|
234
283
|
it 'calls the block with every matching filenames' do
|
|
235
284
|
expect { |blk| described_class.glob('/test*', &blk) }.to \
|
|
236
|
-
yield_successive_args('/test0', '/test1', '/test2')
|
|
285
|
+
yield_successive_args(expected_path('/test0'), expected_path('/test1'), expected_path('/test2'))
|
|
237
286
|
end
|
|
238
287
|
|
|
239
288
|
it 'returns nil' do
|
|
@@ -243,20 +292,22 @@ module MemFs
|
|
|
243
292
|
|
|
244
293
|
context 'when pattern is an array of patterns' do
|
|
245
294
|
it 'returns the list of files matching any pattern' do
|
|
246
|
-
expect(described_class.glob(['/*0', '/*1'])).to eq
|
|
295
|
+
expect(described_class.glob(['/*0', '/*1'])).to eq [expected_path('/test0'), expected_path('/test1')]
|
|
247
296
|
end
|
|
248
297
|
end
|
|
249
298
|
end
|
|
250
299
|
|
|
251
300
|
describe '.home' do
|
|
252
301
|
it 'returns the home directory of the current user' do
|
|
253
|
-
|
|
302
|
+
# Dir.home uses forward slashes; ENV['HOME'] may have backslashes on Windows
|
|
303
|
+
expect(described_class.home).to eq ENV['HOME'].tr('\\', '/')
|
|
254
304
|
end
|
|
255
305
|
|
|
256
306
|
context 'when a username is given' do
|
|
257
307
|
it 'returns the home directory of the given user' do
|
|
258
|
-
|
|
259
|
-
|
|
308
|
+
username = ENV['USER'] || ENV['USERNAME']
|
|
309
|
+
home_dir = described_class.home(username)
|
|
310
|
+
expect(home_dir).to eq ENV['HOME'].tr('\\', '/')
|
|
260
311
|
end
|
|
261
312
|
end
|
|
262
313
|
end
|
|
@@ -267,15 +318,15 @@ module MemFs
|
|
|
267
318
|
expect(File.directory?('/new-folder')).to be true
|
|
268
319
|
end
|
|
269
320
|
|
|
270
|
-
it 'sets directory permissions to default
|
|
321
|
+
it 'sets directory permissions to default 0o777' do
|
|
271
322
|
described_class.mkdir '/new-folder'
|
|
272
|
-
expect(File.stat('/new-folder').mode).to eq(
|
|
323
|
+
expect(File.stat('/new-folder').mode).to eq(0o100777)
|
|
273
324
|
end
|
|
274
325
|
|
|
275
326
|
context 'when permissions are specified' do
|
|
276
327
|
it 'sets directory permissions to specified value' do
|
|
277
|
-
described_class.mkdir '/new-folder',
|
|
278
|
-
expect(File.stat('/new-folder').mode).to eq(
|
|
328
|
+
described_class.mkdir '/new-folder', 0o644
|
|
329
|
+
expect(File.stat('/new-folder').mode).to eq(0o100644)
|
|
279
330
|
end
|
|
280
331
|
end
|
|
281
332
|
|
|
@@ -371,7 +422,87 @@ module MemFs
|
|
|
371
422
|
|
|
372
423
|
describe '.tmpdir' do
|
|
373
424
|
it 'returns /tmp' do
|
|
374
|
-
expect(described_class.tmpdir).to eq '/tmp'
|
|
425
|
+
expect(described_class.tmpdir).to eq expected_path('/tmp')
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
describe '::Tmpname' do
|
|
430
|
+
it 'is defined' do
|
|
431
|
+
expect(described_class.const_defined?(:Tmpname)).to be true
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
it 'responds to .create' do
|
|
435
|
+
expect(described_class::Tmpname).to respond_to(:create)
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
describe '.mktmpdir' do
|
|
440
|
+
context 'when no block is given' do
|
|
441
|
+
it 'creates a temporary directory and returns its path' do
|
|
442
|
+
path = described_class.mktmpdir
|
|
443
|
+
expect(path).to start_with(expected_path('/tmp/d'))
|
|
444
|
+
expect(described_class.exist?(path)).to be true
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it 'accepts a prefix' do
|
|
448
|
+
path = described_class.mktmpdir('myprefix')
|
|
449
|
+
expect(path).to start_with(expected_path('/tmp/myprefix'))
|
|
450
|
+
expect(described_class.exist?(path)).to be true
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
it 'accepts a prefix and suffix as an array' do
|
|
454
|
+
path = described_class.mktmpdir(['prefix_', '_suffix'])
|
|
455
|
+
expect(path).to start_with(expected_path('/tmp/prefix_'))
|
|
456
|
+
expect(path).to end_with('_suffix')
|
|
457
|
+
expect(described_class.exist?(path)).to be true
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
it 'accepts a custom tmpdir' do
|
|
461
|
+
described_class.mkdir('/custom_tmp')
|
|
462
|
+
path = described_class.mktmpdir(nil, '/custom_tmp')
|
|
463
|
+
expect(path).to start_with(expected_path('/custom_tmp/d'))
|
|
464
|
+
expect(described_class.exist?(path)).to be true
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
context 'when a block is given' do
|
|
469
|
+
it 'creates a temporary directory, yields it, and removes it' do
|
|
470
|
+
yielded_path = nil
|
|
471
|
+
described_class.mktmpdir do |path|
|
|
472
|
+
yielded_path = path
|
|
473
|
+
expect(path).to start_with(expected_path('/tmp/d'))
|
|
474
|
+
expect(described_class.exist?(path)).to be true
|
|
475
|
+
end
|
|
476
|
+
expect(described_class.exist?(yielded_path)).to be false
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
it 'removes the directory even if an exception occurs' do
|
|
480
|
+
yielded_path = nil
|
|
481
|
+
expect do
|
|
482
|
+
described_class.mktmpdir do |path|
|
|
483
|
+
yielded_path = path
|
|
484
|
+
expect(described_class.exist?(path)).to be true
|
|
485
|
+
raise 'test exception'
|
|
486
|
+
end
|
|
487
|
+
end.to raise_error('test exception')
|
|
488
|
+
expect(described_class.exist?(yielded_path)).to be false
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
it 'works with a prefix and block' do
|
|
492
|
+
yielded_path = nil
|
|
493
|
+
described_class.mktmpdir('test_') do |path|
|
|
494
|
+
yielded_path = path
|
|
495
|
+
expect(path).to start_with(expected_path('/tmp/test_'))
|
|
496
|
+
expect(described_class.exist?(path)).to be true
|
|
497
|
+
end
|
|
498
|
+
expect(described_class.exist?(yielded_path)).to be false
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
it 'creates unique directory names' do
|
|
503
|
+
path1 = described_class.mktmpdir
|
|
504
|
+
path2 = described_class.mktmpdir
|
|
505
|
+
expect(path1).not_to eq(path2)
|
|
375
506
|
end
|
|
376
507
|
end
|
|
377
508
|
|
|
@@ -408,9 +539,15 @@ module MemFs
|
|
|
408
539
|
end
|
|
409
540
|
end
|
|
410
541
|
|
|
542
|
+
describe '#fileno' do
|
|
543
|
+
it 'raises an exception' do
|
|
544
|
+
expect { subject.fileno }.to raise_exception(NotImplementedError)
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
|
|
411
548
|
describe '#path' do
|
|
412
549
|
it "returns the path parameter passed to dir's constructor" do
|
|
413
|
-
expect(subject.path).to eq '/test'
|
|
550
|
+
expect(subject.path).to eq expected_path('/test')
|
|
414
551
|
end
|
|
415
552
|
end
|
|
416
553
|
|
|
@@ -521,7 +658,7 @@ module MemFs
|
|
|
521
658
|
|
|
522
659
|
describe '#to_path' do
|
|
523
660
|
it "returns the path parameter passed to dir's constructor" do
|
|
524
|
-
expect(subject.to_path).to eq '/test'
|
|
661
|
+
expect(subject.to_path).to eq expected_path('/test')
|
|
525
662
|
end
|
|
526
663
|
end
|
|
527
664
|
end
|
|
@@ -91,16 +91,16 @@ module MemFs
|
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
describe '#path' do
|
|
94
|
-
let(:root) { described_class.new(
|
|
94
|
+
let(:root) { described_class.new(root_path) }
|
|
95
95
|
|
|
96
96
|
it 'returns the directory path' do
|
|
97
97
|
directory.parent = root
|
|
98
|
-
expect(directory.path).to eq('/test')
|
|
98
|
+
expect(directory.path).to eq(expected_path('/test'))
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
context 'when the directory is /' do
|
|
102
102
|
it 'returns /' do
|
|
103
|
-
expect(root.path).to eq(
|
|
103
|
+
expect(root.path).to eq(root_path)
|
|
104
104
|
end
|
|
105
105
|
end
|
|
106
106
|
end
|
|
@@ -54,8 +54,8 @@ module MemFs
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
it_behaves_like 'it has accessors for', :mode do
|
|
57
|
-
let(:value) {
|
|
58
|
-
let(:expected) {
|
|
57
|
+
let(:value) { 0o777 }
|
|
58
|
+
let(:expected) { 0o100777 }
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
it_behaves_like 'it has accessors for', :parent do
|
|
@@ -113,7 +113,13 @@ module MemFs
|
|
|
113
113
|
|
|
114
114
|
describe '#dereferenced_path' do
|
|
115
115
|
it 'returns the entry path' do
|
|
116
|
-
expect(entry.dereferenced_path).to eq('/parent/test')
|
|
116
|
+
expect(entry.dereferenced_path).to eq(expected_path('/parent/test'))
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
describe '#fileno' do
|
|
121
|
+
it 'raises an exception' do
|
|
122
|
+
expect { subject.fileno }.to raise_exception(NotImplementedError)
|
|
117
123
|
end
|
|
118
124
|
end
|
|
119
125
|
|
|
@@ -137,13 +143,13 @@ module MemFs
|
|
|
137
143
|
|
|
138
144
|
describe '#path' do
|
|
139
145
|
it 'returns the complete path of the entry' do
|
|
140
|
-
expect(entry.path).to eq('/parent/test')
|
|
146
|
+
expect(entry.path).to eq(expected_path('/parent/test'))
|
|
141
147
|
end
|
|
142
148
|
end
|
|
143
149
|
|
|
144
150
|
describe 'paths' do
|
|
145
151
|
it 'returns an array containing the entry path' do
|
|
146
|
-
expect(entry.paths).to eq ['/parent/test']
|
|
152
|
+
expect(entry.paths).to eq [expected_path('/parent/test')]
|
|
147
153
|
end
|
|
148
154
|
end
|
|
149
155
|
|
|
@@ -54,7 +54,7 @@ module MemFs
|
|
|
54
54
|
it 'returns its target path' do
|
|
55
55
|
_fs.touch('/test-file')
|
|
56
56
|
symlink = described_class.new('/test-link', '/test-file')
|
|
57
|
-
expect(symlink.dereferenced_path).to eq('/test-file')
|
|
57
|
+
expect(symlink.dereferenced_path).to eq(expected_path('/test-file'))
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|