memfs 0.5.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.
data/lib/memfs/file.rb CHANGED
@@ -1,28 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
  require 'memfs/filesystem_access'
3
5
  require 'memfs/io'
4
6
 
5
7
  module MemFs
6
- class File
8
+ class File < IO
7
9
  extend FilesystemAccess
8
10
  extend SingleForwardable
9
- extend IO::ClassMethods
10
11
 
11
12
  include Enumerable
12
13
  include FilesystemAccess
13
- include OriginalFile::Constants
14
- include IO::InstanceMethods
15
14
 
15
+ PATH_SEPARATOR = '/'
16
16
  ALT_SEPARATOR = nil
17
17
 
18
18
  MODE_MAP = {
19
- 'r' => RDONLY,
19
+ 'r' => RDONLY,
20
20
  'r+' => RDWR,
21
- 'w' => CREAT | TRUNC | WRONLY,
21
+ 'w' => CREAT | TRUNC | WRONLY,
22
22
  'w+' => CREAT | TRUNC | RDWR,
23
- 'a' => CREAT | APPEND | WRONLY,
23
+ 'a' => CREAT | APPEND | WRONLY,
24
24
  'a+' => CREAT | APPEND | RDWR
25
- }
25
+ }.freeze
26
26
 
27
27
  SEPARATOR = '/'
28
28
  SUCCESS = 0
@@ -30,46 +30,54 @@ module MemFs
30
30
  @umask = nil
31
31
 
32
32
  def_delegators :original_file_class,
33
- :basename,
34
- :dirname,
35
- :extname,
36
- :fnmatch,
37
- :join,
38
- :path,
39
- :split
40
-
41
- [
42
- :blockdev?,
43
- :chardev?,
44
- :directory?,
45
- :executable?,
46
- :executable_real?,
47
- :file?,
48
- :grpowned?,
49
- :owned?,
50
- :pipe?,
51
- :readable?,
52
- :readable_real?,
53
- :setgid?,
54
- :setuid?,
55
- :socket?,
56
- :sticky?,
57
- :writable?,
58
- :writable_real?,
59
- :zero?
33
+ :basename,
34
+ :dirname,
35
+ :extname,
36
+ :fnmatch,
37
+ :join,
38
+ :path,
39
+ :split
40
+
41
+ %i[
42
+ blockdev?
43
+ chardev?
44
+ directory?
45
+ executable?
46
+ executable_real?
47
+ file?
48
+ grpowned?
49
+ owned?
50
+ pipe?
51
+ readable?
52
+ readable_real?
53
+ setgid?
54
+ setuid?
55
+ socket?
56
+ sticky?
57
+ writable?
58
+ writable_real?
59
+ zero?
60
60
  ].each do |query_method|
61
- define_singleton_method(query_method) do |path| # def directory?(path)
62
- stat_query(path, query_method) # stat_query(path, :directory?)
63
- end # end
61
+ # def directory?(path)
62
+ # stat_query(path, :directory?)
63
+ # end
64
+ define_singleton_method(query_method) do |path|
65
+ stat_query(path, query_method)
66
+ end
64
67
  end
65
68
 
66
- [
67
- :world_readable?,
68
- :world_writable?
69
+ class << self; alias empty? zero?; end
70
+
71
+ %i[
72
+ world_readable?
73
+ world_writable?
69
74
  ].each do |query_method|
70
- define_singleton_method(query_method) do |path| # def directory?(path)
71
- stat_query(path, query_method, false) # stat_query(path, :directory?, false)
72
- end # end
75
+ # def directory?(path)
76
+ # stat_query(path, :directory?, false)
77
+ # end
78
+ define_singleton_method(query_method) do |path|
79
+ stat_query(path, query_method, force_boolean: false)
80
+ end
73
81
  end
74
82
 
75
83
  def self.absolute_path(path, dir_string = fs.pwd)
@@ -80,6 +88,10 @@ module MemFs
80
88
  stat(path).atime
81
89
  end
82
90
 
91
+ def self.birthtime(path)
92
+ stat(path).birthtime
93
+ end
94
+
83
95
  def self.chmod(mode_int, *paths)
84
96
  paths.each do |path|
85
97
  fs.chmod mode_int, path
@@ -100,7 +112,7 @@ module MemFs
100
112
  def self.exists?(path)
101
113
  !!fs.find(path)
102
114
  end
103
- class << self; alias_method :exist?, :exists?; end
115
+ class << self; alias exist? exists?; end
104
116
 
105
117
  def self.expand_path(file_name, dir_string = fs.pwd)
106
118
  original_file_class.expand_path(file_name, dir_string)
@@ -110,10 +122,12 @@ module MemFs
110
122
  fs.find!(path) && lstat(path).ftype
111
123
  end
112
124
 
113
- class << self; alias_method :fnmatch?, :fnmatch; end
125
+ class << self; alias fnmatch? fnmatch; end
114
126
 
115
127
  def self.identical?(path1, path2)
116
- fs.find!(path1).dereferenced === fs.find!(path2).dereferenced
128
+ path1 = path1.path if path1.respond_to?(:path)
129
+ path2 = path2.path if path2.respond_to?(:path)
130
+ fs.find!(path1).dereferenced.equal? fs.find!(path2).dereferenced
117
131
  rescue Errno::ENOENT
118
132
  false
119
133
  end
@@ -180,15 +194,13 @@ module MemFs
180
194
 
181
195
  def self.size?(path)
182
196
  file = fs.find(path)
183
- if file && file.size > 0
184
- file.size
185
- else
186
- false
187
- end
197
+ size = file&.size.to_i
198
+
199
+ size.positive? ? size : false
188
200
  end
189
201
 
190
202
  def self.stat(path)
191
- Stat.new(path, true)
203
+ Stat.new(path, dereference: true)
192
204
  end
193
205
 
194
206
  def self.symlink(old_name, new_name)
@@ -197,7 +209,7 @@ module MemFs
197
209
  end
198
210
 
199
211
  def self.symlink?(path)
200
- lstat_query(path, :symlink?)
212
+ lstat_query?(path, :symlink?)
201
213
  end
202
214
 
203
215
  def self.truncate(path, length)
@@ -214,12 +226,10 @@ module MemFs
214
226
  end
215
227
 
216
228
  def self.unlink(*paths)
217
- paths.each do |path|
218
- fs.unlink(path)
219
- end
229
+ paths.each { |path| fs.unlink(path) }
220
230
  paths.size
221
231
  end
222
- class << self; alias_method :delete, :unlink; end
232
+ class << self; alias delete unlink; end
223
233
 
224
234
  def self.utime(atime, mtime, *file_names)
225
235
  file_names.each do |file_name|
@@ -229,32 +239,43 @@ module MemFs
229
239
  file_names.size
230
240
  end
231
241
 
232
- attr_reader :path
242
+ attr_reader :path # rubocop:disable Lint/DuplicateMethods
233
243
 
244
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
234
245
  def initialize(filename, mode = File::RDONLY, *perm_and_or_opt)
246
+ super()
247
+
235
248
  opt = perm_and_or_opt.last.is_a?(Hash) ? perm_and_or_opt.pop : {}
236
- perm = perm_and_or_opt.shift
237
- if perm_and_or_opt.size > 0
238
- fail ArgumentError, 'wrong number of arguments (4 for 1..3)'
239
- end
249
+ perm_and_or_opt.shift
250
+
251
+ fail ArgumentError, 'wrong number of arguments (4 for 1..3)' if perm_and_or_opt.any?
240
252
 
241
253
  @path = filename
242
- @external_encoding = opt[:external_encoding] && Encoding.find(opt[:external_encoding])
254
+ @external_encoding =
255
+ opt[:external_encoding] && Encoding.find(opt[:external_encoding])
243
256
 
244
257
  self.closed = false
245
258
  self.opening_mode = str_to_mode_int(mode)
246
259
 
247
260
  fs.touch(filename) if create_file?
248
261
 
249
- self.entry = fs.find(filename)
262
+ self.entry = fs.find!(filename)
263
+ # FIXME: this is an ugly way to ensure a symlink has a target
264
+ entry.dereferenced
250
265
 
266
+ entry.pos = 0 if entry.respond_to?(:pos=)
251
267
  entry.content.clear if truncate_file?
252
268
  end
269
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
253
270
 
254
271
  def atime
255
272
  File.atime(path)
256
273
  end
257
274
 
275
+ def birthtime
276
+ File.birthtime(path)
277
+ end
278
+
258
279
  def chmod(mode_int)
259
280
  fs.chmod(mode_int, path)
260
281
  SUCCESS
@@ -289,15 +310,9 @@ module MemFs
289
310
  File.truncate(path, integer)
290
311
  end
291
312
 
292
- private
293
-
294
313
  def self.dereference_name(path)
295
314
  entry = fs.find(path)
296
- if entry
297
- entry.dereferenced_name
298
- else
299
- basename(path)
300
- end
315
+ entry ? entry.dereferenced_name : basename(path)
301
316
  end
302
317
  private_class_method :dereference_name
303
318
 
@@ -321,16 +336,16 @@ module MemFs
321
336
  end
322
337
  private_class_method :original_file_class
323
338
 
324
- def self.stat_query(path, query, force_boolean = true)
339
+ def self.stat_query(path, query, force_boolean: true)
325
340
  response = fs.find(path) && stat(path).public_send(query)
326
- force_boolean ? !!(response) : response
341
+ force_boolean ? !!response : response
327
342
  end
328
343
  private_class_method :stat_query
329
344
 
330
- def self.lstat_query(path, query)
345
+ def self.lstat_query?(path, query)
331
346
  response = fs.find(path) && lstat(path).public_send(query)
332
- !!(response)
347
+ !!response
333
348
  end
334
- private_class_method :lstat_query
349
+ private_class_method :lstat_query?
335
350
  end
336
351
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
  require 'memfs/fake/directory'
3
5
  require 'memfs/fake/file'
@@ -7,29 +9,30 @@ module MemFs
7
9
  class FileSystem
8
10
  include Singleton
9
11
 
10
- attr_accessor :working_directory
11
- attr_accessor :registred_entries
12
- attr_accessor :root
12
+ attr_accessor :registred_entries,
13
+ :root,
14
+ :working_directory
13
15
 
14
16
  def basename(path)
15
17
  File.basename(path)
16
18
  end
17
19
 
18
- def chdir(path, &block)
20
+ def chdir(path)
19
21
  destination = find_directory!(path)
20
22
 
21
23
  previous_directory = working_directory
22
24
  self.working_directory = destination
23
25
 
24
- block.call if block
26
+ yield if block_given?
25
27
  ensure
26
- self.working_directory = previous_directory if block
28
+ self.working_directory = previous_directory if block_given?
27
29
  end
28
30
 
29
31
  def clear!
30
- self.root = Fake::Directory.new('/')
31
- mkdir '/tmp'
32
- chdir '/'
32
+ MemFs.reset_platform_root!
33
+ self.root = Fake::Directory.new(MemFs.platform_root)
34
+ mkdir File.join(MemFs.platform_root, 'tmp')
35
+ chdir MemFs.platform_root
33
36
  end
34
37
 
35
38
  def chmod(mode_int, file_name)
@@ -51,7 +54,9 @@ module MemFs
51
54
  end
52
55
 
53
56
  def find(path)
54
- if path == '/'
57
+ path = MemFs.normalize_path(path)
58
+
59
+ if MemFs.root_path?(path)
55
60
  root
56
61
  elsif dirname(path) == '.'
57
62
  working_directory.find(path)
@@ -80,7 +85,7 @@ module MemFs
80
85
  def getwd
81
86
  working_directory.path
82
87
  end
83
- alias_method :pwd, :getwd
88
+ alias pwd getwd
84
89
 
85
90
  def initialize
86
91
  clear!
@@ -96,7 +101,7 @@ module MemFs
96
101
  find_parent!(new_name).add_entry link
97
102
  end
98
103
 
99
- def mkdir(path, mode = 0777)
104
+ def mkdir(path, mode = 0o777)
100
105
  fail Errno::EEXIST, path if find(path)
101
106
  directory = Fake::Directory.new(path)
102
107
  directory.mode = mode
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MemFs
2
4
  module FilesystemAccess
3
5
  private