memfs 0.4.1 → 0.4.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 70a8628ef207a62b0e968c52b562a999eb9b17eb
4
+ data.tar.gz: da534038352ee4290851b8dc4f2f7aef7bed7cf5
5
+ SHA512:
6
+ metadata.gz: c47dc6fe5eb179d3ee6d4e1e439e714d19920af0d474fa6166c1c8d75eb0c6a9c37d5115cf9db627e1801e0318dcb077620f05c87387428698061282610541a5
7
+ data.tar.gz: 218c397cacf5071ea1f83cfa06b12b8420bfef293390c652066f5548f6f9b7e9fba78e6d19af76f6d73a59bf0939a3ffdbcb66f7b649a9073ce9406c04fd5da0
@@ -0,0 +1,29 @@
1
+ AlignParameters:
2
+ Enabled: false
3
+
4
+ Blocks:
5
+ Enabled: false
6
+
7
+ ClassLength:
8
+ Enabled: false
9
+
10
+ Documentation:
11
+ Enabled: false
12
+
13
+ DoubleNegation:
14
+ Enabled: false
15
+
16
+ EmptyLinesAroundBody:
17
+ Enabled: false
18
+
19
+ LineLength:
20
+ Enabled: false
21
+
22
+ PercentLiteralDelimiters:
23
+ Enabled: false
24
+
25
+ SpecialGlobalVars:
26
+ Enabled: false
27
+
28
+ TrivialAccessors:
29
+ Enabled: false
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## HEAD
4
+
5
+ ## 0.4.2
6
+
7
+ * ADD: `File#external_encoding`
8
+ * FIX: Undefined local variable or method `fs' for MemFs::File
9
+
3
10
  ## 0.4.1
4
11
 
5
12
  * FIX: Support for 1.9.3 broken by File::FNM_EXTGLOB
data/Guardfile CHANGED
@@ -1,8 +1,7 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- guard 'rspec' do
1
+ guard :rspec, cmd: 'bundle exec rspec', all_after_pass: true, all_on_start: true do
5
2
  watch(%r{^spec/.+_spec\.rb$})
6
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
- watch('spec/spec_helper.rb') { "spec" }
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+
5
+ watch('lib/memfs/io.rb') { |m| 'spec/memfs/file_spec.rb' }
6
+ watch('spec/spec_helper.rb') { 'spec' }
8
7
  end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # MemFs
1
+ ![MemFs Logo](https://raw.github.com/simonc/memfs/master/memfs.png)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/memfs.png)](http://badge.fury.io/rb/memfs)
4
4
  [![Build Status](https://secure.travis-ci.org/simonc/memfs.png?branch=master)](http://travis-ci.org/simonc/memfs)
@@ -83,7 +83,7 @@ you `spec_helper.rb` file:
83
83
  ``` ruby
84
84
  Rspec.configure do |c|
85
85
  c.around(:each, memfs: true) do |example|
86
- MemFs.activate { example.run }
86
+ MemFs.activate { example.run }
87
87
  end
88
88
  end
89
89
  ```
@@ -93,7 +93,7 @@ And then write your specs like this:
93
93
  ``` ruby
94
94
  it "creates a file", memfs: true do
95
95
  subject.create_file('test.rb')
96
- expect(File.exists?('test.rb')).to be_true
96
+ expect(File.exists?('test.rb')).to be true
97
97
  end
98
98
  ```
99
99
 
@@ -107,7 +107,7 @@ describe FileCreator do
107
107
  it "creates a file" do
108
108
  MemFs.activate do
109
109
  subject.create_file('test.rb')
110
- expect(File.exists?('test.rb')).to be_true
110
+ expect(File.exists?('test.rb')).to be true
111
111
  end
112
112
  end
113
113
  end
@@ -126,7 +126,7 @@ describe FileCreator do
126
126
  describe '.create_file' do
127
127
  it "creates a file" do
128
128
  subject.create_file('test.rb')
129
- expect(File.exists?('test.rb')).to be_true
129
+ expect(File.exists?('test.rb')).to be true
130
130
  end
131
131
  end
132
132
  end
@@ -145,7 +145,7 @@ end
145
145
 
146
146
  ## Requirements
147
147
 
148
- * Ruby 2.0+
148
+ * Ruby 1.9.3 or newer
149
149
 
150
150
  ## Known issues
151
151
 
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'memfs'
4
4
 
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
 
7
- task :default => :spec
7
+ task default: :spec
8
8
 
9
9
  desc 'Compares a MemFs class to the original Ruby one ' \
10
10
  '(set CLASS to the compared class)'
@@ -36,3 +36,11 @@ task :compare do
36
36
  puts
37
37
  puts implemented_i_methods - original_i_methods
38
38
  end
39
+
40
+ task :console do
41
+ require 'irb'
42
+ require 'irb/completion'
43
+ require 'memfs'
44
+ ARGV.clear
45
+ IRB.start
46
+ end
@@ -16,8 +16,6 @@ require 'fileutils'
16
16
  # MemFs.deactivate!
17
17
  # # Everything back to normal
18
18
  module MemFs
19
- extend self
20
-
21
19
  # Keeps track of the original Ruby Dir class.
22
20
  OriginalDir = ::Dir
23
21
 
@@ -56,6 +54,7 @@ module MemFs
56
54
  ensure
57
55
  deactivate!
58
56
  end
57
+ module_function :activate
59
58
 
60
59
  # Activates the fake file system.
61
60
  #
@@ -76,12 +75,13 @@ module MemFs
76
75
  remove_const :Dir
77
76
  remove_const :File
78
77
 
79
- const_set :Dir, MemFs::Dir
78
+ const_set :Dir, MemFs::Dir
80
79
  const_set :File, MemFs::File
81
80
  end
82
81
 
83
82
  MemFs::FileSystem.instance.clear!
84
83
  end
84
+ module_function :activate!
85
85
 
86
86
  # Deactivates the fake file system.
87
87
  #
@@ -94,10 +94,11 @@ module MemFs
94
94
  remove_const :Dir
95
95
  remove_const :File
96
96
 
97
- const_set :Dir, MemFs::OriginalDir
97
+ const_set :Dir, MemFs::OriginalDir
98
98
  const_set :File, MemFs::OriginalFile
99
99
  end
100
100
  end
101
+ module_function :deactivate!
101
102
 
102
103
  # Creates a file and all its parent directories.
103
104
  #
@@ -114,4 +115,5 @@ module MemFs
114
115
  FileUtils.touch path
115
116
  end
116
117
  end
118
+ module_function :touch
117
119
  end
@@ -4,6 +4,7 @@ module MemFs
4
4
  class Dir
5
5
  extend FilesystemAccess
6
6
  include Enumerable
7
+ include FilesystemAccess
7
8
 
8
9
  attr_reader :pos
9
10
 
@@ -13,13 +14,11 @@ module MemFs
13
14
 
14
15
  def self.chdir(path, &block)
15
16
  fs.chdir path, &block
16
- return 0
17
+ 0
17
18
  end
18
19
 
19
20
  def self.chroot(path)
20
- unless Process.uid.zero?
21
- raise Errno::EPERM, path
22
- end
21
+ fail Errno::EPERM, path unless Process.uid.zero?
23
22
 
24
23
  dir = fs.find_directory!(path)
25
24
  dir.name = '/'
@@ -27,14 +26,14 @@ module MemFs
27
26
  0
28
27
  end
29
28
 
30
- def self.entries(dirname, opts = {})
29
+ def self.entries(dirname, _opts = {})
31
30
  fs.entries(dirname)
32
31
  end
33
32
 
34
33
  def self.exists?(path)
35
34
  File.directory?(path)
36
35
  end
37
- class << self; alias :exist? :exists?; end
36
+ class << self; alias_method :exist?, :exists?; end
38
37
 
39
38
  def self.foreach(dirname, &block)
40
39
  return to_enum(__callee__, dirname) unless block
@@ -45,19 +44,20 @@ module MemFs
45
44
  def self.getwd
46
45
  fs.getwd
47
46
  end
48
- class << self; alias :pwd :getwd; end
47
+ class << self; alias_method :pwd, :getwd; end
49
48
 
50
49
  def self.glob(patterns, flags = 0)
51
50
  patterns = [*patterns]
52
51
  list = fs.paths.select do |path|
53
- patterns.any? do |pattern|
54
- File.fnmatch?(pattern, path, flags | GLOB_FLAGS)
55
- end
56
- end
52
+ patterns.any? do |pattern|
53
+ File.fnmatch?(pattern, path, flags | GLOB_FLAGS)
54
+ end
55
+ end
57
56
  # FIXME: ugly special case for /* and /
58
57
  list.delete('/') if patterns.first == '/*'
59
58
  return list unless block_given?
60
- list.each { |path| yield path } and nil
59
+ list.each { |path| yield path }
60
+ nil
61
61
  end
62
62
 
63
63
  def self.home(*args)
@@ -89,8 +89,8 @@ module MemFs
89
89
  end
90
90
 
91
91
  class << self
92
- alias :delete :rmdir
93
- alias :unlink :rmdir
92
+ alias_method :delete, :rmdir
93
+ alias_method :unlink, :rmdir
94
94
  end
95
95
 
96
96
  def initialize(path)
@@ -101,9 +101,7 @@ module MemFs
101
101
  end
102
102
 
103
103
  def close
104
- if state == :closed
105
- fail IOError, 'closed directory'
106
- end
104
+ fail IOError, 'closed directory' if state == :closed
107
105
  self.state = :closed
108
106
  end
109
107
 
@@ -115,7 +113,7 @@ module MemFs
115
113
  def path
116
114
  entry.path
117
115
  end
118
- alias :to_path :path
116
+ alias_method :to_path, :path
119
117
 
120
118
  def pos=(position)
121
119
  seek(position)
@@ -135,9 +133,7 @@ module MemFs
135
133
  end
136
134
 
137
135
  def seek(position)
138
- if (0..max_seek).cover?(position)
139
- @pos = position
140
- end
136
+ @pos = position if (0..max_seek).cover?(position)
141
137
  self
142
138
  end
143
139
 
@@ -50,8 +50,8 @@ module MemFs
50
50
  @dev ||= rand(1000)
51
51
  end
52
52
 
53
- def find(path)
54
- raise Errno::ENOTDIR, self.path
53
+ def find(_path)
54
+ fail Errno::ENOTDIR, path
55
55
  end
56
56
 
57
57
  def initialize(path = nil)
@@ -1,4 +1,4 @@
1
- require "delegate"
1
+ require 'delegate'
2
2
 
3
3
  module MemFs
4
4
  module Fake
@@ -20,7 +20,8 @@ module MemFs
20
20
  def puts(*strings)
21
21
  strings.each do |str|
22
22
  @string << str
23
- @string << $/ unless str.end_with?($/)
23
+ next if str.end_with?($/)
24
+ @string << $/
24
25
  end
25
26
  end
26
27
 
@@ -1,25 +1,31 @@
1
1
  require 'forwardable'
2
2
  require 'memfs/filesystem_access'
3
+ require 'memfs/io'
3
4
 
4
5
  module MemFs
5
6
  class File
6
7
  extend FilesystemAccess
7
8
  extend SingleForwardable
9
+ extend IO::ClassMethods
10
+
8
11
  include Enumerable
9
12
  include FilesystemAccess
10
13
  include OriginalFile::Constants
14
+ include IO::InstanceMethods
11
15
 
12
16
  MODE_MAP = {
13
17
  'r' => RDONLY,
14
18
  'r+' => RDWR,
15
- 'w' => CREAT|TRUNC|WRONLY,
16
- 'w+' => CREAT|TRUNC|RDWR,
17
- 'a' => CREAT|APPEND|WRONLY,
18
- 'a+' => CREAT|APPEND|RDWR
19
+ 'w' => CREAT | TRUNC | WRONLY,
20
+ 'w+' => CREAT | TRUNC | RDWR,
21
+ 'a' => CREAT | APPEND | WRONLY,
22
+ 'a+' => CREAT | APPEND | RDWR
19
23
  }
20
24
 
21
25
  SUCCESS = 0
22
26
 
27
+ @umask = nil
28
+
23
29
  def_delegators :original_file_class,
24
30
  :basename,
25
31
  :dirname,
@@ -45,8 +51,6 @@ module MemFs
45
51
  :setuid?,
46
52
  :socket?,
47
53
  :sticky?,
48
- :world_readable?,
49
- :world_writable?,
50
54
  :writable?,
51
55
  :writable_real?,
52
56
  :zero?
@@ -56,6 +60,15 @@ module MemFs
56
60
  end # end
57
61
  end
58
62
 
63
+ [
64
+ :world_readable?,
65
+ :world_writable?
66
+ ].each do |query_method|
67
+ define_singleton_method(query_method) do |path| # def directory?(path)
68
+ stat_query(path, query_method, false) # stat_query(path, :directory?, false)
69
+ end # end
70
+ end
71
+
59
72
  def self.absolute_path(path, dir_string = fs.pwd)
60
73
  original_file_class.absolute_path(path, dir_string)
61
74
  end
@@ -84,7 +97,7 @@ module MemFs
84
97
  def self.exists?(path)
85
98
  !!fs.find(path)
86
99
  end
87
- class << self; alias :exist? :exists?; end
100
+ class << self; alias_method :exist?, :exists?; end
88
101
 
89
102
  def self.expand_path(file_name, dir_string = fs.pwd)
90
103
  original_file_class.expand_path(file_name, dir_string)
@@ -94,7 +107,7 @@ module MemFs
94
107
  fs.find!(path) && lstat(path).ftype
95
108
  end
96
109
 
97
- class << self; alias :fnmatch? :fnmatch; end
110
+ class << self; alias_method :fnmatch?, :fnmatch; end
98
111
 
99
112
  def self.identical?(path1, path2)
100
113
  fs.find!(path1).dereferenced === fs.find!(path2).dereferenced
@@ -126,7 +139,7 @@ module MemFs
126
139
  end
127
140
 
128
141
  def self.open(filename, mode = RDONLY, *perm_and_opt)
129
- file = self.new(filename, mode, *perm_and_opt)
142
+ file = new(filename, mode, *perm_and_opt)
130
143
 
131
144
  if block_given?
132
145
  yield file
@@ -137,21 +150,6 @@ module MemFs
137
150
  file.close if file && block_given?
138
151
  end
139
152
 
140
- def self.read(path, *args)
141
- options = args.last.is_a?(Hash) ? args.pop : {}
142
- options = { mode: RDONLY, encoding: nil, open_args: nil }.merge(options)
143
- open_args = options[:open_args] ||
144
- [options[:mode], encoding: options[:encoding]]
145
-
146
- length, offset = args
147
-
148
- file = open(path, *open_args)
149
- file.seek(offset || 0)
150
- file.read(length)
151
- ensure
152
- file.close if file
153
- end
154
-
155
153
  def self.readlink(path)
156
154
  fs.find!(path).target
157
155
  end
@@ -179,7 +177,11 @@ module MemFs
179
177
 
180
178
  def self.size?(path)
181
179
  file = fs.find(path)
182
- file && file.size > 0 && file.size
180
+ if file && file.size > 0
181
+ file.size
182
+ else
183
+ false
184
+ end
183
185
  end
184
186
 
185
187
  def self.stat(path)
@@ -214,7 +216,7 @@ module MemFs
214
216
  end
215
217
  paths.size
216
218
  end
217
- class << self; alias :delete :unlink; end
219
+ class << self; alias_method :delete, :unlink; end
218
220
 
219
221
  def self.utime(atime, mtime, *file_names)
220
222
  file_names.each do |file_name|
@@ -226,13 +228,17 @@ module MemFs
226
228
 
227
229
  attr_reader :path
228
230
 
229
- def initialize(filename, mode = RDONLY, perm = nil, opt = nil)
230
- unless opt.nil? || opt.is_a?(Hash)
231
- raise ArgumentError, "wrong number of arguments (4 for 1..3)"
231
+ def initialize(filename, mode = File::RDONLY, *perm_and_or_opt)
232
+ opt = perm_and_or_opt.last.is_a?(Hash) ? perm_and_or_opt.pop : {}
233
+ perm = perm_and_or_opt.shift
234
+ if perm_and_or_opt.size > 0
235
+ fail ArgumentError, 'wrong number of arguments (4 for 1..3)'
232
236
  end
233
237
 
234
238
  @path = filename
239
+ @external_encoding = opt[:external_encoding] && Encoding.find(opt[:external_encoding])
235
240
 
241
+ self.closed = false
236
242
  self.opening_mode = str_to_mode_int(mode)
237
243
 
238
244
  fs.touch(filename) if create_file?
@@ -242,6 +248,10 @@ module MemFs
242
248
  entry.content.clear if truncate_file?
243
249
  end
244
250
 
251
+ def atime
252
+ File.atime(path)
253
+ end
254
+
245
255
  def chmod(mode_int)
246
256
  fs.chmod(mode_int, path)
247
257
  SUCCESS
@@ -252,76 +262,35 @@ module MemFs
252
262
  SUCCESS
253
263
  end
254
264
 
255
- def close
256
- self.closed = true
265
+ def ctime
266
+ File.ctime(path)
257
267
  end
258
268
 
259
- def closed?
260
- closed
269
+ def flock(*)
270
+ SUCCESS
261
271
  end
262
272
 
263
- def each(sep = $/, &block)
264
- return to_enum(__callee__) unless block_given?
265
- fail IOError, 'not opened for reading' unless readable?
266
- content.each_line(sep) { |line| block.call(line) }
267
- self
273
+ def mtime
274
+ File.mtime(path)
268
275
  end
269
276
 
270
277
  def lstat
271
278
  File.lstat(path)
272
279
  end
273
280
 
274
- def pos
275
- entry.pos
276
- end
277
-
278
- def puts(text)
279
- raise IOError, 'not opened for writing' unless writable?
280
-
281
- content.puts text
282
- end
283
-
284
- def read(length = nil, buffer = '')
285
- default = length ? nil : ''
286
- content.read(length, buffer) || default
287
- end
288
-
289
- def seek(amount, whence = IO::SEEK_SET)
290
- new_pos = case whence
291
- when IO::SEEK_CUR then entry.pos + amount
292
- when IO::SEEK_END then content.to_s.length + amount
293
- when IO::SEEK_SET then amount
294
- end
295
-
296
- if new_pos.nil? || new_pos < 0
297
- raise Errno::EINVAL, path
298
- end
299
-
300
- entry.pos = new_pos and 0
301
- end
302
-
303
281
  def size
304
282
  entry.size
305
283
  end
306
284
 
307
- def stat
308
- File.stat(path)
309
- end
310
-
311
- def write(string)
312
- raise IOError, 'not opened for writing' unless writable?
313
-
314
- content.write(string.to_s)
285
+ def truncate(integer)
286
+ File.truncate(path, integer)
315
287
  end
316
288
 
317
289
  private
318
290
 
319
- attr_accessor :closed,
320
- :entry,
321
- :opening_mode
322
-
323
291
  def self.dereference_name(path)
324
- if entry = fs.find(path)
292
+ entry = fs.find(path)
293
+ if entry
325
294
  entry.dereferenced_name
326
295
  else
327
296
  basename(path)
@@ -349,47 +318,16 @@ module MemFs
349
318
  end
350
319
  private_class_method :original_file_class
351
320
 
352
- def self.stat_query(path, query)
353
- fs.find(path) && stat(path).public_send(query)
321
+ def self.stat_query(path, query, force_boolean = true)
322
+ response = fs.find(path) && stat(path).public_send(query)
323
+ force_boolean ? !!(response) : response
354
324
  end
355
325
  private_class_method :stat_query
356
326
 
357
327
  def self.lstat_query(path, query)
358
- fs.find(path) && lstat(path).public_send(query)
328
+ response = fs.find(path) && lstat(path).public_send(query)
329
+ !!(response)
359
330
  end
360
331
  private_class_method :lstat_query
361
-
362
- def content
363
- entry.content
364
- end
365
-
366
- def str_to_mode_int(mode)
367
- return mode unless mode.is_a?(String)
368
-
369
- unless mode =~ /\A([rwa]\+?)([bt])?\z/
370
- raise ArgumentError, "invalid access mode #{mode}"
371
- end
372
-
373
- mode_str = $~[1]
374
- MODE_MAP[mode_str]
375
- end
376
-
377
- def create_file?
378
- (opening_mode & File::CREAT).nonzero?
379
- end
380
-
381
- def readable?
382
- (opening_mode & File::RDWR).nonzero? ||
383
- (opening_mode | File::RDONLY).zero?
384
- end
385
-
386
- def truncate_file?
387
- (opening_mode & File::TRUNC).nonzero?
388
- end
389
-
390
- def writable?
391
- (opening_mode & File::WRONLY).nonzero? ||
392
- (opening_mode & File::RDWR).nonzero?
393
- end
394
332
  end
395
333
  end