fakefs 0.16.0 → 0.17.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bfa54005c100676feb93956681fe9cd686030fe16e3dab3a54109e5c29b2361
4
- data.tar.gz: 30c51f9bcf1e221ca4cd3fbb43ee987979c7fa57b2aa1865f9387bfab755d66b
3
+ metadata.gz: 2615742cb54b7cea91ad40e51e1b1baf037ea9295eff338b0432fc20f1ea9483
4
+ data.tar.gz: e9e136d1eb2d10a18b0470ed45c8058b88656af040d45136f78a53fb21bf42c0
5
5
  SHA512:
6
- metadata.gz: 6929e502b22c9f1f632b0d98379caad07a7abcda53c658fb258d321dda15e53d60e4c927365beb6ec62d2e9d30c77aa70e746e0cd693bf6f02256c64eb4ab5a2
7
- data.tar.gz: 2d80c942fbfea67e1dfa031f1b859115cefe783e9cb35a246a7f44b6f1d55511c40a758782dafad2557eefcbf7cabcea7f338c35a6f207a7ea94ec204bb99aea
6
+ metadata.gz: 790f25734bd4b9bf2c4b82750421bbe40114a591efa327b909b61e0ef341360f5bdbde7c5d99c06a3931f46d655710f1fc7c302a24b67590cb849e506e750450
7
+ data.tar.gz: 73578d236fa95d8307311c87c9fba693c101295bdc915b2bc6adda0c074e9ea5eb782121af5cc3c3446cf8292d57a6ed8dd5c6979a4cdee9be2fb11053c4b65c
@@ -119,7 +119,7 @@ module FakeFS
119
119
 
120
120
  def self.glob(pattern, flags = 0, &block)
121
121
  matches_for_pattern = lambda do |matcher|
122
- [FileSystem.find(matcher, flags) || []].flatten.map do |e|
122
+ [FileSystem.find(matcher, flags, true) || []].flatten.map do |e|
123
123
  if Dir.pwd.match(%r{\A/?\z}) ||
124
124
  !e.to_s.match(%r{\A#{Dir.pwd}/?})
125
125
  e.to_s
@@ -53,16 +53,20 @@ module FakeFS
53
53
  class << self
54
54
  alias exists? exist?
55
55
 
56
- # Assuming that everyone can read and write files
57
- alias readable? exist?
58
- alias writable? exist?
59
-
60
56
  # Assume nothing is sticky.
61
57
  def sticky?(_path)
62
58
  false
63
59
  end
64
60
  end
65
61
 
62
+ def self.readable?(path)
63
+ File.lstat(path).readable?
64
+ end
65
+
66
+ def self.writable?(path)
67
+ File.lstat(path).writable?
68
+ end
69
+
66
70
  def self.mtime(path)
67
71
  if exists?(path)
68
72
  FileSystem.find(path).mtime
@@ -363,13 +367,28 @@ module FakeFS
363
367
  'file'
364
368
  end
365
369
 
366
- # assumes, like above, that all files are readable and writable.
367
370
  def readable?
368
- true
371
+ # a file is readable if, and only if, it has the following bits:
372
+ # 4 ( read permission )
373
+ # 5 ( read + execute permission )
374
+ # 6 ( read + write permission )
375
+ # 7 ( read + write + execute permission )
376
+ # for each group we will isolate the wanted numbers ( for owner, world, or group )
377
+ # and see if the third bit is set ( as that is the bit for read )
378
+ read_bit = 4
379
+ check_if_bit_set(read_bit)
369
380
  end
370
381
 
371
382
  def writable?
372
- true
383
+ # a file is writable if, and only if, it has the following bits:
384
+ # 2 ( write permission )
385
+ # 3 ( write + execute permission )
386
+ # 6 ( read + write permission )
387
+ # 7 ( read + write + execute permission )
388
+ # for each group we will isolate the wanted numbers ( for owner, world, or group )
389
+ # and see if the second bit is set ( as that is the bit for write )
390
+ write_bit = 2
391
+ check_if_bit_set(write_bit)
373
392
  end
374
393
 
375
394
  # Assume nothing is sticky.
@@ -412,6 +431,41 @@ module FakeFS
412
431
  def <=>(other)
413
432
  @mtime <=> other.mtime
414
433
  end
434
+
435
+ private
436
+
437
+ def check_if_bit_set(bit)
438
+ # get user's group and user ids
439
+ # NOTE: I am picking `Process` over `Etc` as we use `Process`
440
+ # when instaniating file classes. It may be worth it to ensure
441
+ # our Process/Group detection scheme is robust in all cases
442
+ uid = Process.uid
443
+ gid = Process.gid
444
+
445
+ # check if bit set for owner
446
+ owner_bits = (@mode >> 6) & 0o7
447
+ if uid == @uid
448
+ # the user is locked out of the file if they are owner of the file
449
+ # but do not have the bit set at the user level
450
+ return true if owner_bits & bit == bit
451
+ return false
452
+ end
453
+
454
+ # check if bit set for group
455
+ group_bits = (@mode >> 3) & 0o7
456
+ if gid == @gid
457
+ # the user is locked out of the file if they are in the group that
458
+ # owns the file but do not have the bit set at the group level
459
+ return true if group_bits & bit == bit
460
+ return false
461
+ end
462
+
463
+ # check if bit set for world
464
+ world_bits = @mode & 0o7
465
+ return true if world_bits & bit == bit
466
+
467
+ false
468
+ end
415
469
  end
416
470
 
417
471
  attr_reader :path
@@ -20,13 +20,13 @@ module FakeFS
20
20
  fs.entries
21
21
  end
22
22
 
23
- def find(path, find_flags = 0)
23
+ def find(path, find_flags = 0, gave_char_class = false)
24
24
  parts = path_parts(normalize_path(path))
25
25
  return fs if parts.empty? # '/'
26
26
 
27
27
  entries = Globber.expand(path).flat_map do |pattern|
28
28
  parts = path_parts(normalize_path(pattern))
29
- find_recurser(fs, parts, find_flags).flatten
29
+ find_recurser(fs, parts, find_flags, gave_char_class).flatten
30
30
  end
31
31
 
32
32
  case entries.length
@@ -88,6 +88,7 @@ module FakeFS
88
88
  dir_levels.push dir if blk
89
89
 
90
90
  raise Errno::ENOENT, dir unless new_dir
91
+ raise Errno::ENOTDIR, dir unless File.directory? new_dir
91
92
 
92
93
  dir_levels.push dir unless blk
93
94
  yield(dir) if blk
@@ -116,7 +117,7 @@ module FakeFS
116
117
 
117
118
  private
118
119
 
119
- def find_recurser(dir, parts, find_flags = 0)
120
+ def find_recurser(dir, parts, find_flags = 0, gave_char_class = false)
120
121
  return [] unless dir.respond_to? :[]
121
122
  pattern, *parts = parts
122
123
  matches =
@@ -139,14 +140,14 @@ module FakeFS
139
140
  end
140
141
  else
141
142
  Globber.expand(pattern).flat_map do |subpattern|
142
- dir.matches(Globber.regexp(subpattern, find_flags))
143
+ dir.matches(Globber.regexp(subpattern, find_flags, gave_char_class))
143
144
  end
144
145
  end
145
146
 
146
147
  if parts.empty? # we're done recursing
147
148
  matches
148
149
  else
149
- matches.map { |entry| find_recurser(entry, parts, find_flags) }
150
+ matches.map { |entry| find_recurser(entry, parts, find_flags, gave_char_class) }
150
151
  end
151
152
  end
152
153
 
@@ -60,7 +60,7 @@ module FakeFS
60
60
  drop_root(result).reject(&:empty?)
61
61
  end
62
62
 
63
- def regexp(pattern, find_flags = 0)
63
+ def regexp(pattern, find_flags = 0, gave_char_class = false)
64
64
  pattern = pattern.to_s
65
65
 
66
66
  regex_body =
@@ -73,6 +73,12 @@ module FakeFS
73
73
  .gsub(')', '\)')
74
74
  .gsub('$', '\$')
75
75
 
76
+ # unless we're expecting character class contructs in regexes, escape all brackets
77
+ # since if we're expecting them, the string should already be properly escaped
78
+ unless gave_char_class
79
+ regex_body = regex_body.gsub('[', '\[').gsub(']', '\]')
80
+ end
81
+
76
82
  # This matches nested braces and attempts to do something correct most of the time
77
83
  # There are known issues (i.e. {,*,*/*}) that cannot be resolved with out a total
78
84
  # refactoring
@@ -1,7 +1,7 @@
1
1
  module FakeFS
2
2
  # Version module
3
3
  module Version
4
- VERSION = '0.16.0'.freeze
4
+ VERSION = '0.17.0'.freeze
5
5
 
6
6
  def self.to_s
7
7
  VERSION
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fakefs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2018-07-11 00:00:00.000000000 Z
15
+ date: 2018-07-16 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bump