memfs 0.0.2 → 0.1.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 +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +4 -0
- data/README.md +7 -1
- data/lib/memfs/dir.rb +1 -1
- data/lib/memfs/fake/directory.rb +4 -0
- data/lib/memfs/fake/entry.rb +20 -3
- data/lib/memfs/fake/file.rb +8 -0
- data/lib/memfs/fake/file/content.rb +4 -0
- data/lib/memfs/fake/symlink.rb +24 -0
- data/lib/memfs/file.rb +89 -7
- data/lib/memfs/file/stat.rb +127 -4
- data/lib/memfs/file_system.rb +0 -8
- data/lib/memfs/version.rb +1 -1
- data/spec/memfs/fake/directory_spec.rb +6 -0
- data/spec/memfs/fake/entry_spec.rb +54 -24
- data/spec/memfs/fake/file/content_spec.rb +9 -0
- data/spec/memfs/fake/file_spec.rb +22 -0
- data/spec/memfs/fake/symlink_spec.rb +70 -0
- data/spec/memfs/file/stat_spec.rb +728 -84
- data/spec/memfs/file_spec.rb +1028 -39
- data/spec/memfs/file_system_spec.rb +63 -35
- metadata +3 -5
- data/.DS_Store +0 -0
- data/lib/fileutils.rb +0 -1738
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 015cda23b6a9dbae4b0bd9665312b4da277d95bd
|
4
|
+
data.tar.gz: c4328852dd8ae3ce91c1b0d777d90d3d8438194f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed264906f48c92c3622a674dfecdc7c279739f210e2c6607aaca2f31e9990620634ed0607fd4b80e61123bed3d22208989de546706e71a03855921627589453a
|
7
|
+
data.tar.gz: a83c9c316d30710cecdf298ff77c4c495693b562351f7c204c15030f5566ea3291bd14130bea081aad5c22983ca48852cf3b1dae15e22075a9c8678998eca92a
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
# MemFs
|
1
|
+
# MemFs
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/memfs)
|
4
|
+
[](http://travis-ci.org/simonc/memfs)
|
5
|
+
[](https://codeclimate.com/github/simonc/memfs)
|
6
|
+
[](https://coveralls.io/r/simonc/memfs?branch=master)
|
2
7
|
|
3
8
|
MemFs is an in-memory filesystem that can be used for your tests.
|
4
9
|
|
@@ -114,6 +119,7 @@ end
|
|
114
119
|
## Known issues
|
115
120
|
|
116
121
|
* MemFs doesn't implement IO so FileUtils.copy_stream is still the original one
|
122
|
+
* Pipes and Sockets are not handled for now
|
117
123
|
|
118
124
|
## TODO
|
119
125
|
|
data/lib/memfs/dir.rb
CHANGED
data/lib/memfs/fake/directory.rb
CHANGED
data/lib/memfs/fake/entry.rb
CHANGED
@@ -12,8 +12,13 @@ module MemFs
|
|
12
12
|
OEXEC = 00004
|
13
13
|
RSTICK = 01000
|
14
14
|
USTICK = 05000
|
15
|
+
SETUID = 04000
|
16
|
+
SETGID = 02000
|
15
17
|
|
16
18
|
attr_accessor :atime,
|
19
|
+
:block_device,
|
20
|
+
:character_device,
|
21
|
+
:ctime,
|
17
22
|
:gid,
|
18
23
|
:mtime,
|
19
24
|
:name,
|
@@ -33,6 +38,14 @@ module MemFs
|
|
33
38
|
self
|
34
39
|
end
|
35
40
|
|
41
|
+
def dereferenced_name
|
42
|
+
name
|
43
|
+
end
|
44
|
+
|
45
|
+
def dereferenced_path
|
46
|
+
path
|
47
|
+
end
|
48
|
+
|
36
49
|
def dev
|
37
50
|
@dev ||= rand(1000)
|
38
51
|
end
|
@@ -42,14 +55,14 @@ module MemFs
|
|
42
55
|
end
|
43
56
|
|
44
57
|
def initialize(path = nil)
|
45
|
-
current_user = Etc.getpwuid
|
46
58
|
time = Time.now
|
47
59
|
self.atime = time
|
48
|
-
self.
|
60
|
+
self.ctime = time
|
61
|
+
self.gid = Process.egid
|
49
62
|
self.mode = 0666 - MemFs::File.umask
|
50
63
|
self.mtime = time
|
51
64
|
self.name = MemFs::File.basename(path || '')
|
52
|
-
self.uid =
|
65
|
+
self.uid = Process.euid
|
53
66
|
end
|
54
67
|
|
55
68
|
def ino
|
@@ -68,6 +81,10 @@ module MemFs
|
|
68
81
|
def touch
|
69
82
|
self.atime = self.mtime = Time.now
|
70
83
|
end
|
84
|
+
|
85
|
+
def type
|
86
|
+
'unknown'
|
87
|
+
end
|
71
88
|
end
|
72
89
|
end
|
73
90
|
end
|
data/lib/memfs/fake/file.rb
CHANGED
data/lib/memfs/fake/symlink.rb
CHANGED
@@ -11,6 +11,20 @@ module MemFs
|
|
11
11
|
@dereferenced ||= fs.find!(target).dereferenced
|
12
12
|
end
|
13
13
|
|
14
|
+
def dereferenced_name
|
15
|
+
real_target.dereferenced_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def dereferenced_path
|
19
|
+
dereferenced.dereferenced_path
|
20
|
+
end
|
21
|
+
|
22
|
+
def find(path)
|
23
|
+
dereferenced.find(path)
|
24
|
+
rescue Errno::ENOENT
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
14
28
|
def initialize(path, target)
|
15
29
|
super(path)
|
16
30
|
@target = target
|
@@ -27,6 +41,16 @@ module MemFs
|
|
27
41
|
def respond_to_missing?(meth, include_private)
|
28
42
|
dereferenced.respond_to?(meth, include_private) || super
|
29
43
|
end
|
44
|
+
|
45
|
+
def type
|
46
|
+
'link'
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def real_target
|
52
|
+
fs.find(target) || Entry.new(target)
|
53
|
+
end
|
30
54
|
end
|
31
55
|
end
|
32
56
|
end
|
data/lib/memfs/file.rb
CHANGED
@@ -25,8 +25,42 @@ module MemFs
|
|
25
25
|
def_delegators :original_file_class,
|
26
26
|
:basename,
|
27
27
|
:dirname,
|
28
|
+
:extname,
|
29
|
+
:fnmatch,
|
28
30
|
:join,
|
29
|
-
:path
|
31
|
+
:path,
|
32
|
+
:split
|
33
|
+
|
34
|
+
%i[
|
35
|
+
blockdev?
|
36
|
+
chardev?
|
37
|
+
directory?
|
38
|
+
executable?
|
39
|
+
executable_real?
|
40
|
+
file?
|
41
|
+
grpowned?
|
42
|
+
owned?
|
43
|
+
pipe?
|
44
|
+
readable?
|
45
|
+
readable_real?
|
46
|
+
setgid?
|
47
|
+
setuid?
|
48
|
+
socket?
|
49
|
+
sticky?
|
50
|
+
world_readable?
|
51
|
+
world_writable?
|
52
|
+
writable?
|
53
|
+
writable_real?
|
54
|
+
zero?
|
55
|
+
].each do |query_method|
|
56
|
+
define_singleton_method(query_method) do |path| # def directory?(path)
|
57
|
+
stat_query(path, query_method) # stat_query(path, :directory?)
|
58
|
+
end # end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.absolute_path(path, dir_string = fs.pwd)
|
62
|
+
original_file_class.absolute_path(path, dir_string)
|
63
|
+
end
|
30
64
|
|
31
65
|
def self.atime(path)
|
32
66
|
stat(path).atime
|
@@ -45,12 +79,12 @@ module MemFs
|
|
45
79
|
paths.size
|
46
80
|
end
|
47
81
|
|
48
|
-
def self.
|
49
|
-
|
82
|
+
def self.ctime(path)
|
83
|
+
stat(path).ctime
|
50
84
|
end
|
51
85
|
|
52
86
|
def self.exists?(path)
|
53
|
-
|
87
|
+
!!fs.find(path)
|
54
88
|
end
|
55
89
|
class << self; alias :exist? :exists?; end
|
56
90
|
|
@@ -58,10 +92,12 @@ module MemFs
|
|
58
92
|
original_file_class.expand_path(file_name, dir_string)
|
59
93
|
end
|
60
94
|
|
61
|
-
def self.
|
62
|
-
fs.find(path)
|
95
|
+
def self.ftype(path)
|
96
|
+
fs.find!(path) && lstat(path).ftype
|
63
97
|
end
|
64
98
|
|
99
|
+
class << self; alias :fnmatch? :fnmatch; end
|
100
|
+
|
65
101
|
def self.identical?(path1, path2)
|
66
102
|
fs.find!(path1).dereferenced === fs.find!(path2).dereferenced
|
67
103
|
rescue Errno::ENOENT
|
@@ -117,6 +153,14 @@ module MemFs
|
|
117
153
|
fs.find!(path).target
|
118
154
|
end
|
119
155
|
|
156
|
+
def self.realdirpath(path, dir_string = fs.pwd)
|
157
|
+
loose_dereference_path(absolute_path(path, dir_string))
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.realpath(path, dir_string = fs.pwd)
|
161
|
+
dereference_path(absolute_path(path, dir_string))
|
162
|
+
end
|
163
|
+
|
120
164
|
def self.rename(old_name, new_name)
|
121
165
|
fs.rename(old_name, new_name)
|
122
166
|
SUCCESS
|
@@ -130,6 +174,11 @@ module MemFs
|
|
130
174
|
fs.find!(path).size
|
131
175
|
end
|
132
176
|
|
177
|
+
def self.size?(path)
|
178
|
+
file = fs.find(path)
|
179
|
+
file && file.size > 0 && file.size
|
180
|
+
end
|
181
|
+
|
133
182
|
def self.stat(path)
|
134
183
|
Stat.new(path, true)
|
135
184
|
end
|
@@ -140,7 +189,12 @@ module MemFs
|
|
140
189
|
end
|
141
190
|
|
142
191
|
def self.symlink?(path)
|
143
|
-
|
192
|
+
lstat_query(path, :symlink?)
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.truncate(path, length)
|
196
|
+
fs.find!(path).content.truncate(length)
|
197
|
+
SUCCESS
|
144
198
|
end
|
145
199
|
|
146
200
|
def self.umask(integer = nil)
|
@@ -257,10 +311,38 @@ module MemFs
|
|
257
311
|
|
258
312
|
private
|
259
313
|
|
314
|
+
def self.dereference_name(path)
|
315
|
+
if entry = fs.find(path)
|
316
|
+
entry.dereferenced_name
|
317
|
+
else
|
318
|
+
basename(path)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def self.dereference_dir_path(path)
|
323
|
+
dereference_path(dirname(path))
|
324
|
+
end
|
325
|
+
|
326
|
+
def self.dereference_path(path)
|
327
|
+
fs.find!(path).dereferenced_path
|
328
|
+
end
|
329
|
+
|
330
|
+
def self.loose_dereference_path(path)
|
331
|
+
join(dereference_dir_path(path), dereference_name(path))
|
332
|
+
end
|
333
|
+
|
260
334
|
def self.original_file_class
|
261
335
|
MemFs::OriginalFile
|
262
336
|
end
|
263
337
|
|
338
|
+
def self.stat_query(path, query)
|
339
|
+
fs.find(path) && stat(path).public_send(query)
|
340
|
+
end
|
341
|
+
|
342
|
+
def self.lstat_query(path, query)
|
343
|
+
fs.find(path) && lstat(path).public_send(query)
|
344
|
+
end
|
345
|
+
|
264
346
|
def str_to_mode_int(mode)
|
265
347
|
return mode unless mode.is_a?(String)
|
266
348
|
|
data/lib/memfs/file/stat.rb
CHANGED
@@ -12,6 +12,7 @@ module MemFs
|
|
12
12
|
def_delegators :entry,
|
13
13
|
:atime,
|
14
14
|
:blksize,
|
15
|
+
:ctime,
|
15
16
|
:dev,
|
16
17
|
:gid,
|
17
18
|
:ino,
|
@@ -19,12 +20,36 @@ module MemFs
|
|
19
20
|
:mtime,
|
20
21
|
:uid
|
21
22
|
|
23
|
+
def blockdev?
|
24
|
+
!!entry.block_device
|
25
|
+
end
|
26
|
+
|
27
|
+
def chardev?
|
28
|
+
!!entry.character_device
|
29
|
+
end
|
30
|
+
|
22
31
|
def directory?
|
23
|
-
|
32
|
+
entry.is_a?(Fake::Directory)
|
33
|
+
end
|
34
|
+
|
35
|
+
def executable?
|
36
|
+
user_executable? || group_executable? || !!world_executable?
|
37
|
+
end
|
38
|
+
|
39
|
+
def executable_real?
|
40
|
+
user_executable_real? || group_executable_real? || !!world_executable?
|
24
41
|
end
|
25
42
|
|
26
43
|
def file?
|
27
|
-
|
44
|
+
entry.is_a?(Fake::File)
|
45
|
+
end
|
46
|
+
|
47
|
+
def ftype
|
48
|
+
entry.type
|
49
|
+
end
|
50
|
+
|
51
|
+
def grpowned?
|
52
|
+
gid == Process.egid
|
28
53
|
end
|
29
54
|
|
30
55
|
def initialize(path, dereference = false)
|
@@ -32,16 +57,114 @@ module MemFs
|
|
32
57
|
@entry = dereference ? entry.dereferenced : entry
|
33
58
|
end
|
34
59
|
|
60
|
+
def owned?
|
61
|
+
uid == Process.euid
|
62
|
+
end
|
63
|
+
|
64
|
+
def pipe?
|
65
|
+
false
|
66
|
+
end
|
67
|
+
|
68
|
+
def readable?
|
69
|
+
user_readable? || group_readable? || !!world_readable?
|
70
|
+
end
|
71
|
+
|
72
|
+
def readable_real?
|
73
|
+
user_readable_real? || group_readable_real? || !!world_readable?
|
74
|
+
end
|
75
|
+
|
76
|
+
def setgid?
|
77
|
+
!!(entry.mode & Fake::Entry::SETGID).nonzero?
|
78
|
+
end
|
79
|
+
|
80
|
+
def setuid?
|
81
|
+
!!(entry.mode & Fake::Entry::SETUID).nonzero?
|
82
|
+
end
|
83
|
+
|
84
|
+
def socket?
|
85
|
+
false
|
86
|
+
end
|
87
|
+
|
35
88
|
def sticky?
|
36
89
|
!!(entry.mode & Fake::Entry::USTICK).nonzero?
|
37
90
|
end
|
38
91
|
|
39
92
|
def symlink?
|
40
|
-
|
93
|
+
entry.is_a?(Fake::Symlink)
|
94
|
+
end
|
95
|
+
|
96
|
+
def world_readable?
|
97
|
+
entry.mode - 0100000 if (entry.mode & Fake::Entry::OREAD).nonzero?
|
41
98
|
end
|
42
99
|
|
43
100
|
def world_writable?
|
44
|
-
entry.mode if (entry.mode & Fake::Entry::OWRITE).nonzero?
|
101
|
+
entry.mode - 0100000 if (entry.mode & Fake::Entry::OWRITE).nonzero?
|
102
|
+
end
|
103
|
+
|
104
|
+
def writable?
|
105
|
+
user_writable? || group_writable? || !!world_writable?
|
106
|
+
end
|
107
|
+
|
108
|
+
def writable_real?
|
109
|
+
user_writable_real? || group_writable_real? || !!world_writable?
|
110
|
+
end
|
111
|
+
|
112
|
+
def zero?
|
113
|
+
entry.content && entry.content.empty?
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def group_executable?
|
119
|
+
grpowned? && !!(mode & Fake::Entry::GEXEC).nonzero?
|
120
|
+
end
|
121
|
+
|
122
|
+
def group_executable_real?
|
123
|
+
Process.gid == gid && !!(mode & Fake::Entry::GEXEC).nonzero?
|
124
|
+
end
|
125
|
+
|
126
|
+
def group_readable?
|
127
|
+
grpowned? && !!(mode & Fake::Entry::GREAD).nonzero?
|
128
|
+
end
|
129
|
+
|
130
|
+
def group_readable_real?
|
131
|
+
Process.gid == gid && !!(mode & Fake::Entry::GREAD).nonzero?
|
132
|
+
end
|
133
|
+
|
134
|
+
def group_writable?
|
135
|
+
grpowned? && !!(mode & Fake::Entry::GWRITE).nonzero?
|
136
|
+
end
|
137
|
+
|
138
|
+
def group_writable_real?
|
139
|
+
Process.gid == gid && !!(mode & Fake::Entry::GWRITE).nonzero?
|
140
|
+
end
|
141
|
+
|
142
|
+
def user_executable?
|
143
|
+
owned? && !!(mode & Fake::Entry::UEXEC).nonzero?
|
144
|
+
end
|
145
|
+
|
146
|
+
def user_executable_real?
|
147
|
+
Process.uid == uid && !!(mode & Fake::Entry::UEXEC).nonzero?
|
148
|
+
end
|
149
|
+
|
150
|
+
def user_readable?
|
151
|
+
owned? && !!(mode & Fake::Entry::UREAD).nonzero?
|
152
|
+
end
|
153
|
+
|
154
|
+
def user_readable_real?
|
155
|
+
Process.uid == uid && !!(mode & Fake::Entry::UREAD).nonzero?
|
156
|
+
end
|
157
|
+
|
158
|
+
def user_writable?
|
159
|
+
owned? && !!(mode & Fake::Entry::UWRITE).nonzero?
|
160
|
+
end
|
161
|
+
|
162
|
+
def user_writable_real?
|
163
|
+
Process.uid == uid && !!(mode & Fake::Entry::UWRITE).nonzero?
|
164
|
+
end
|
165
|
+
|
166
|
+
def world_executable?
|
167
|
+
entry.mode - 0100000 if (entry.mode & Fake::Entry::OEXEC).nonzero?
|
45
168
|
end
|
46
169
|
end
|
47
170
|
end
|