fakefs 0.4.0 → 0.4.1
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/.travis.yml +9 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +31 -0
- data/README.markdown +65 -29
- data/Rakefile +16 -13
- data/fakefs.gemspec +11 -11
- data/lib/fakefs/base.rb +69 -32
- data/lib/fakefs/dir.rb +22 -15
- data/lib/fakefs/fake/dir.rb +36 -10
- data/lib/fakefs/fake/file.rb +7 -2
- data/lib/fakefs/file.rb +90 -17
- data/lib/fakefs/file_system.rb +18 -10
- data/lib/fakefs/fileutils.rb +84 -41
- data/lib/fakefs/pathname.rb +864 -0
- data/lib/fakefs/safe.rb +2 -0
- data/lib/fakefs/version.rb +1 -1
- data/test/fakefs_test.rb +355 -49
- data/test/file/stat_test.rb +36 -0
- data/test/safe_test.rb +41 -3
- data/test/test_helper.rb +8 -1
- metadata +61 -60
data/lib/fakefs/fake/dir.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
module FakeFS
|
2
|
-
class FakeDir
|
3
|
-
attr_accessor :name, :parent
|
4
|
-
attr_reader :ctime, :
|
2
|
+
class FakeDir
|
3
|
+
attr_accessor :name, :parent, :mode, :uid, :gid, :mtime, :atime
|
4
|
+
attr_reader :ctime, :content
|
5
5
|
|
6
6
|
def initialize(name = nil, parent = nil)
|
7
|
-
@name
|
8
|
-
@parent
|
9
|
-
@ctime
|
10
|
-
@mtime
|
7
|
+
@name = name
|
8
|
+
@parent = parent
|
9
|
+
@ctime = Time.now
|
10
|
+
@mtime = @ctime
|
11
|
+
@atime = @ctime
|
12
|
+
@mode = 0100000 + (0777 - File.umask)
|
13
|
+
@uid = Process.uid
|
14
|
+
@gid = Process.gid
|
15
|
+
@content = ""
|
16
|
+
@entries = {}
|
11
17
|
end
|
12
18
|
|
13
19
|
def entry
|
@@ -15,12 +21,12 @@ module FakeFS
|
|
15
21
|
end
|
16
22
|
|
17
23
|
def inspect
|
18
|
-
"(FakeDir name:#{name.inspect} parent:#{parent.to_s.inspect} size:#{size})"
|
24
|
+
"(FakeDir name:#{name.inspect} parent:#{parent.to_s.inspect} size:#{@entries.size})"
|
19
25
|
end
|
20
26
|
|
21
27
|
def clone(parent = nil)
|
22
28
|
clone = Marshal.load(Marshal.dump(self))
|
23
|
-
clone.each do |
|
29
|
+
clone.entries.each do |value|
|
24
30
|
value.parent = clone
|
25
31
|
end
|
26
32
|
clone.parent = parent if parent
|
@@ -37,11 +43,31 @@ module FakeFS
|
|
37
43
|
end
|
38
44
|
end
|
39
45
|
|
46
|
+
def empty?
|
47
|
+
@entries.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
def entries
|
51
|
+
@entries.values
|
52
|
+
end
|
53
|
+
|
54
|
+
def matches(pattern)
|
55
|
+
@entries.reject {|k,v| pattern !~ k }.values
|
56
|
+
end
|
57
|
+
|
58
|
+
def [](name)
|
59
|
+
@entries[name]
|
60
|
+
end
|
61
|
+
|
62
|
+
def []=(name, value)
|
63
|
+
@entries[name] = value
|
64
|
+
end
|
65
|
+
|
40
66
|
def delete(node = self)
|
41
67
|
if node == self
|
42
68
|
parent.delete(self)
|
43
69
|
else
|
44
|
-
|
70
|
+
@entries.delete(node.name)
|
45
71
|
end
|
46
72
|
end
|
47
73
|
end
|
data/lib/fakefs/fake/file.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
module FakeFS
|
2
2
|
class FakeFile
|
3
|
-
attr_accessor :name, :parent, :content, :mtime
|
3
|
+
attr_accessor :name, :parent, :content, :mtime, :atime, :mode, :uid, :gid
|
4
4
|
attr_reader :ctime
|
5
5
|
|
6
6
|
class Inode
|
7
7
|
def initialize(file_owner)
|
8
|
-
|
8
|
+
#1.9.3 when possible set default external encoding
|
9
|
+
@content = "".respond_to?(:encode) ? "".encode(Encoding.default_external) : ""
|
9
10
|
@links = [file_owner]
|
10
11
|
end
|
11
12
|
|
@@ -34,6 +35,10 @@ module FakeFS
|
|
34
35
|
@inode = Inode.new(self)
|
35
36
|
@ctime = Time.now
|
36
37
|
@mtime = @ctime
|
38
|
+
@atime = @ctime
|
39
|
+
@mode = 0100000 + (0666 - File.umask)
|
40
|
+
@uid = Process.uid
|
41
|
+
@gid = Process.gid
|
37
42
|
end
|
38
43
|
|
39
44
|
attr_accessor :inode
|
data/lib/fakefs/file.rb
CHANGED
@@ -2,8 +2,6 @@ require 'stringio'
|
|
2
2
|
|
3
3
|
module FakeFS
|
4
4
|
class File < StringIO
|
5
|
-
PATH_SEPARATOR = '/'
|
6
|
-
|
7
5
|
MODES = [
|
8
6
|
READ_ONLY = "r",
|
9
7
|
READ_WRITE = "r+",
|
@@ -23,8 +21,8 @@ module FakeFS
|
|
23
21
|
RealFile::EXCL |
|
24
22
|
RealFile::NONBLOCK |
|
25
23
|
RealFile::TRUNC |
|
26
|
-
RealFile::NOCTTY |
|
27
|
-
RealFile::SYNC
|
24
|
+
(RealFile.const_defined?(:NOCTTY) ? RealFile::NOCTTY : 0) |
|
25
|
+
(RealFile.const_defined?(:SYNC) ? RealFile::SYNC : 0)
|
28
26
|
|
29
27
|
FILE_CREATION_BITMASK = RealFile::CREAT
|
30
28
|
|
@@ -69,9 +67,18 @@ module FakeFS
|
|
69
67
|
end
|
70
68
|
end
|
71
69
|
|
70
|
+
def self.atime(path)
|
71
|
+
if exists?(path)
|
72
|
+
FileSystem.find(path).atime
|
73
|
+
else
|
74
|
+
raise Errno::ENOENT
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
72
78
|
def self.utime(atime, mtime, *paths)
|
73
79
|
paths.each do |path|
|
74
80
|
if exists?(path)
|
81
|
+
FileSystem.find(path).atime = atime
|
75
82
|
FileSystem.find(path).mtime = mtime
|
76
83
|
else
|
77
84
|
raise Errno::ENOENT
|
@@ -140,9 +147,10 @@ module FakeFS
|
|
140
147
|
symlink.target
|
141
148
|
end
|
142
149
|
|
143
|
-
def self.read(path)
|
150
|
+
def self.read(path, *args)
|
144
151
|
file = new(path)
|
145
152
|
if file.exists?
|
153
|
+
FileSystem.find(path).atime = Time.now
|
146
154
|
file.read
|
147
155
|
else
|
148
156
|
raise Errno::ENOENT
|
@@ -224,8 +232,24 @@ module FakeFS
|
|
224
232
|
return RealFile.split(path)
|
225
233
|
end
|
226
234
|
|
235
|
+
def self.chmod(mode_int, filename)
|
236
|
+
FileSystem.find(filename).mode = 0100000 + mode_int
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.chown(owner_int, group_int, filename)
|
240
|
+
file = FileSystem.find(filename)
|
241
|
+
owner_int.is_a?(Fixnum) or raise TypeError, "can't convert String into Integer"
|
242
|
+
group_int.is_a?(Fixnum) or raise TypeError, "can't convert String into Integer"
|
243
|
+
file.uid = owner_int
|
244
|
+
file.gid = group_int
|
245
|
+
end
|
246
|
+
|
247
|
+
def self.umask
|
248
|
+
RealFile.umask
|
249
|
+
end
|
250
|
+
|
227
251
|
class Stat
|
228
|
-
attr_reader :ctime, :mtime
|
252
|
+
attr_reader :ctime, :mtime, :atime, :mode, :uid, :gid
|
229
253
|
|
230
254
|
def initialize(file, __lstat = false)
|
231
255
|
if !File.exists?(file)
|
@@ -237,6 +261,10 @@ module FakeFS
|
|
237
261
|
@__lstat = __lstat
|
238
262
|
@ctime = @fake_file.ctime
|
239
263
|
@mtime = @fake_file.mtime
|
264
|
+
@atime = @fake_file.atime
|
265
|
+
@mode = @fake_file.mode
|
266
|
+
@uid = @fake_file.uid
|
267
|
+
@gid = @fake_file.gid
|
240
268
|
end
|
241
269
|
|
242
270
|
def symlink?
|
@@ -247,6 +275,14 @@ module FakeFS
|
|
247
275
|
File.directory?(@file)
|
248
276
|
end
|
249
277
|
|
278
|
+
# assumes, like above, that all files are readable and writable
|
279
|
+
def readable?
|
280
|
+
true
|
281
|
+
end
|
282
|
+
def writable?
|
283
|
+
true
|
284
|
+
end
|
285
|
+
|
250
286
|
def nlink
|
251
287
|
@fake_file.links.size
|
252
288
|
end
|
@@ -258,13 +294,23 @@ module FakeFS
|
|
258
294
|
File.size(@file)
|
259
295
|
end
|
260
296
|
end
|
297
|
+
|
298
|
+
def zero?
|
299
|
+
size == 0
|
300
|
+
end
|
301
|
+
|
302
|
+
include Comparable
|
303
|
+
|
304
|
+
def <=>(other)
|
305
|
+
@mtime <=> other.mtime
|
306
|
+
end
|
261
307
|
end
|
262
308
|
|
263
309
|
attr_reader :path
|
264
310
|
|
265
311
|
def initialize(path, mode = READ_ONLY, perm = nil)
|
266
312
|
@path = path
|
267
|
-
@mode = mode
|
313
|
+
@mode = mode.is_a?(Hash) ? (mode[:mode] || READ_ONLY) : mode
|
268
314
|
@file = FileSystem.find(path)
|
269
315
|
@autoclose = true
|
270
316
|
|
@@ -272,13 +318,19 @@ module FakeFS
|
|
272
318
|
|
273
319
|
file_creation_mode? ? create_missing_file : check_file_existence!
|
274
320
|
|
275
|
-
super(@file.content, mode)
|
321
|
+
super(@file.content, @mode)
|
276
322
|
end
|
277
323
|
|
278
324
|
def exists?
|
279
325
|
true
|
280
326
|
end
|
281
327
|
|
328
|
+
def write(str)
|
329
|
+
val = super(str)
|
330
|
+
@file.mtime = Time.now
|
331
|
+
val
|
332
|
+
end
|
333
|
+
|
282
334
|
alias_method :tell=, :pos=
|
283
335
|
alias_method :sysread, :read
|
284
336
|
alias_method :syswrite, :write
|
@@ -289,6 +341,11 @@ module FakeFS
|
|
289
341
|
undef_method :size
|
290
342
|
undef_method :string
|
291
343
|
undef_method :string=
|
344
|
+
if RUBY_PLATFORM == 'java'
|
345
|
+
undef_method :to_channel
|
346
|
+
undef_method :to_outputstream
|
347
|
+
undef_method :to_inputstream
|
348
|
+
end
|
292
349
|
|
293
350
|
def ioctl(integer_cmd, arg)
|
294
351
|
raise NotImplementedError
|
@@ -326,15 +383,7 @@ module FakeFS
|
|
326
383
|
end
|
327
384
|
|
328
385
|
def atime
|
329
|
-
|
330
|
-
end
|
331
|
-
|
332
|
-
def chmod(mode_int)
|
333
|
-
raise NotImplementedError
|
334
|
-
end
|
335
|
-
|
336
|
-
def chown(owner_int, group_int)
|
337
|
-
raise NotImplementedError
|
386
|
+
self.class.atime(@path)
|
338
387
|
end
|
339
388
|
|
340
389
|
def ctime
|
@@ -349,6 +398,17 @@ module FakeFS
|
|
349
398
|
self.class.mtime(@path)
|
350
399
|
end
|
351
400
|
|
401
|
+
def chmod(mode_int)
|
402
|
+
@file.mode = 0100000 + mode_int
|
403
|
+
end
|
404
|
+
|
405
|
+
def chown(owner_int, group_int)
|
406
|
+
owner_int.is_a?(Fixnum) or raise TypeError, "can't convert String into Integer"
|
407
|
+
group_int.is_a?(Fixnum) or raise TypeError, "can't convert String into Integer"
|
408
|
+
@file.uid = owner_int
|
409
|
+
@file.gid = group_int
|
410
|
+
end
|
411
|
+
|
352
412
|
if RUBY_VERSION >= "1.9"
|
353
413
|
def binmode?
|
354
414
|
raise NotImplementedError
|
@@ -374,6 +434,14 @@ module FakeFS
|
|
374
434
|
@autoclose
|
375
435
|
end
|
376
436
|
|
437
|
+
def autoclose?
|
438
|
+
@autoclose ? true : false
|
439
|
+
end
|
440
|
+
|
441
|
+
def autoclose=(autoclose)
|
442
|
+
@autoclose = autoclose
|
443
|
+
end
|
444
|
+
|
377
445
|
alias_method :fdatasync, :flush
|
378
446
|
|
379
447
|
def size
|
@@ -381,6 +449,11 @@ module FakeFS
|
|
381
449
|
end
|
382
450
|
end
|
383
451
|
|
452
|
+
if RUBY_VERSION >= "1.9.3"
|
453
|
+
def advise(advice, offset=0, len=0)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
384
457
|
private
|
385
458
|
|
386
459
|
def check_modes!
|
data/lib/fakefs/file_system.rb
CHANGED
@@ -16,7 +16,7 @@ module FakeFS
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def files
|
19
|
-
fs.
|
19
|
+
fs.entries
|
20
20
|
end
|
21
21
|
|
22
22
|
def find(path)
|
@@ -46,19 +46,20 @@ module FakeFS
|
|
46
46
|
|
47
47
|
# copies directories and files from the real filesystem
|
48
48
|
# into our fake one
|
49
|
-
def clone(path)
|
49
|
+
def clone(path, target = nil)
|
50
50
|
path = File.expand_path(path)
|
51
51
|
pattern = File.join(path, '**', '*')
|
52
52
|
files = RealFile.file?(path) ? [path] : [path] + RealDir.glob(pattern, RealFile::FNM_DOTMATCH)
|
53
53
|
|
54
54
|
files.each do |f|
|
55
|
+
target_path = target ? f.gsub(path, target) : f
|
55
56
|
if RealFile.file?(f)
|
56
57
|
FileUtils.mkdir_p(File.dirname(f))
|
57
|
-
File.open(
|
58
|
+
File.open(target_path, File::WRITE_ONLY) do |g|
|
58
59
|
g.print RealFile.open(f){|h| h.read }
|
59
60
|
end
|
60
61
|
elsif RealFile.directory?(f)
|
61
|
-
FileUtils.mkdir_p(
|
62
|
+
FileUtils.mkdir_p(target_path)
|
62
63
|
elsif RealFile.symlink?(f)
|
63
64
|
FileUtils.ln_s()
|
64
65
|
end
|
@@ -85,7 +86,7 @@ module FakeFS
|
|
85
86
|
end
|
86
87
|
|
87
88
|
def path_parts(path)
|
88
|
-
path.split(File::
|
89
|
+
drop_root(path.split(File::SEPARATOR)).reject { |part| part.empty? }
|
89
90
|
end
|
90
91
|
|
91
92
|
def normalize_path(path)
|
@@ -103,6 +104,14 @@ module FakeFS
|
|
103
104
|
|
104
105
|
private
|
105
106
|
|
107
|
+
def drop_root(path_parts)
|
108
|
+
# we need to remove parts from root dir at least for windows and jruby
|
109
|
+
return path_parts if path_parts.nil? || path_parts.empty?
|
110
|
+
root = File.expand_path('/').split(File::SEPARATOR).first
|
111
|
+
path_parts.shift if path_parts.first == root
|
112
|
+
path_parts
|
113
|
+
end
|
114
|
+
|
106
115
|
def find_recurser(dir, parts)
|
107
116
|
return [] unless dir.respond_to? :[]
|
108
117
|
|
@@ -113,17 +122,16 @@ module FakeFS
|
|
113
122
|
when ['*']
|
114
123
|
parts = [] # end recursion
|
115
124
|
directories_under(dir).map do |d|
|
116
|
-
d.
|
125
|
+
d.entries.select{|f| f.is_a?(FakeFile) || f.is_a?(FakeDir) }
|
117
126
|
end.flatten.uniq
|
118
127
|
when []
|
119
128
|
parts = [] # end recursion
|
120
|
-
dir.
|
129
|
+
dir.entries.flatten.uniq
|
121
130
|
else
|
122
131
|
directories_under(dir)
|
123
132
|
end
|
124
133
|
else
|
125
|
-
|
126
|
-
dir.reject {|k,v| regexp_pattern !~ k }.values
|
134
|
+
dir.matches /\A#{pattern.gsub('.', '\.').gsub('?','.').gsub('*', '.*').gsub(/\{(.*?)\}/) { "(#{$1.gsub(',', '|')})" }}\Z/
|
127
135
|
end
|
128
136
|
|
129
137
|
if parts.empty? # we're done recursing
|
@@ -134,7 +142,7 @@ module FakeFS
|
|
134
142
|
end
|
135
143
|
|
136
144
|
def directories_under(dir)
|
137
|
-
children = dir.
|
145
|
+
children = dir.entries.select{|f| f.is_a? FakeDir}
|
138
146
|
([dir] + children + children.map{|c| directories_under(c)}).flatten.uniq
|
139
147
|
end
|
140
148
|
end
|
data/lib/fakefs/fileutils.rb
CHANGED
@@ -11,7 +11,7 @@ module FakeFS
|
|
11
11
|
def mkdir(path)
|
12
12
|
parent = path.split('/')
|
13
13
|
parent.pop
|
14
|
-
raise Errno::ENOENT, "No such file or directory - #{path}" unless parent.join == "" || FileSystem.find(parent.join('/'))
|
14
|
+
raise Errno::ENOENT, "No such file or directory - #{path}" unless parent.join == "" || parent.join == "." || FileSystem.find(parent.join('/'))
|
15
15
|
raise Errno::EEXIST, "File exists - #{path}" if FileSystem.find(path)
|
16
16
|
FileSystem.add(path, FakeDir.new)
|
17
17
|
end
|
@@ -23,14 +23,14 @@ module FakeFS
|
|
23
23
|
parent.pop
|
24
24
|
raise Errno::ENOENT, "No such file or directory - #{l}" unless parent.join == "" || FileSystem.find(parent.join('/'))
|
25
25
|
raise Errno::ENOENT, l unless FileSystem.find(l)
|
26
|
-
raise Errno::ENOTEMPTY, l unless FileSystem.find(l).
|
26
|
+
raise Errno::ENOTEMPTY, l unless FileSystem.find(l).empty?
|
27
27
|
rm(l)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
def rm(list, options = {})
|
32
32
|
Array(list).each do |path|
|
33
|
-
FileSystem.delete(path) or raise
|
33
|
+
FileSystem.delete(path) or (!options[:force] && raise(Errno::ENOENT.new(path)))
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -56,50 +56,58 @@ module FakeFS
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def cp(src, dest)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
if !src_file
|
63
|
-
raise Errno::ENOENT, src
|
59
|
+
if src.is_a?(Array) && !File.directory?(dest)
|
60
|
+
raise Errno::ENOTDIR, dest
|
64
61
|
end
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
Array(src).each do |src|
|
64
|
+
dst_file = FileSystem.find(dest)
|
65
|
+
src_file = FileSystem.find(src)
|
69
66
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
67
|
+
if !src_file
|
68
|
+
raise Errno::ENOENT, src
|
69
|
+
end
|
70
|
+
|
71
|
+
if File.directory? src_file
|
72
|
+
raise Errno::EISDIR, src
|
73
|
+
end
|
74
|
+
|
75
|
+
if dst_file && File.directory?(dst_file)
|
76
|
+
FileSystem.add(File.join(dest, src), src_file.entry.clone(dst_file))
|
77
|
+
else
|
78
|
+
FileSystem.delete(dest)
|
79
|
+
FileSystem.add(dest, src_file.entry.clone)
|
80
|
+
end
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
78
84
|
def cp_r(src, dest)
|
79
|
-
|
80
|
-
|
81
|
-
|
85
|
+
Array(src).each do |src|
|
86
|
+
# This error sucks, but it conforms to the original Ruby
|
87
|
+
# method.
|
88
|
+
raise "unknown file type: #{src}" unless dir = FileSystem.find(src)
|
82
89
|
|
83
|
-
|
90
|
+
new_dir = FileSystem.find(dest)
|
84
91
|
|
85
|
-
|
86
|
-
|
87
|
-
|
92
|
+
if new_dir && !File.directory?(dest)
|
93
|
+
raise Errno::EEXIST, dest
|
94
|
+
end
|
88
95
|
|
89
|
-
|
90
|
-
|
91
|
-
|
96
|
+
if !new_dir && !FileSystem.find(dest+'/../')
|
97
|
+
raise Errno::ENOENT, dest
|
98
|
+
end
|
92
99
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
100
|
+
# This last bit is a total abuse and should be thought hard
|
101
|
+
# about and cleaned up.
|
102
|
+
if new_dir
|
103
|
+
if src[-2..-1] == '/.'
|
104
|
+
dir.entries.each{|f| new_dir[f.name] = f.clone(new_dir) }
|
105
|
+
else
|
106
|
+
new_dir[dir.name] = dir.entry.clone(new_dir)
|
107
|
+
end
|
98
108
|
else
|
99
|
-
|
109
|
+
FileSystem.add(dest, dir.entry.clone)
|
100
110
|
end
|
101
|
-
else
|
102
|
-
FileSystem.add(dest, dir.entry.clone)
|
103
111
|
end
|
104
112
|
end
|
105
113
|
|
@@ -118,7 +126,11 @@ module FakeFS
|
|
118
126
|
def chown(user, group, list, options={})
|
119
127
|
list = Array(list)
|
120
128
|
list.each do |f|
|
121
|
-
|
129
|
+
if File.exists?(f)
|
130
|
+
uid = (user.to_s.match(/[0-9]+/) ? user.to_i : Etc.getpwnam(user).uid)
|
131
|
+
gid = (group.to_s.match(/[0-9]+/) ? group.to_i : Etc.getgrnam(group).gid)
|
132
|
+
File.chown(uid, gid, f)
|
133
|
+
else
|
122
134
|
raise Errno::ENOENT, f
|
123
135
|
end
|
124
136
|
end
|
@@ -126,17 +138,48 @@ module FakeFS
|
|
126
138
|
end
|
127
139
|
|
128
140
|
def chown_R(user, group, list, options={})
|
129
|
-
|
141
|
+
list = Array(list)
|
142
|
+
list.each do |file|
|
143
|
+
chown(user, group, file)
|
144
|
+
[FileSystem.find("#{file}/**/**")].flatten.each do |f|
|
145
|
+
chown(user, group, f.to_s)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
list
|
149
|
+
end
|
150
|
+
|
151
|
+
def chmod(mode, list, options={})
|
152
|
+
list = Array(list)
|
153
|
+
list.each do |f|
|
154
|
+
if File.exists?(f)
|
155
|
+
File.chmod(mode, f)
|
156
|
+
else
|
157
|
+
raise Errno::ENOENT, f
|
158
|
+
end
|
159
|
+
end
|
160
|
+
list
|
161
|
+
end
|
162
|
+
|
163
|
+
def chmod_R(mode, list, options={})
|
164
|
+
list = Array(list)
|
165
|
+
list.each do |file|
|
166
|
+
chmod(mode, file)
|
167
|
+
[FileSystem.find("#{file}/**/**")].flatten.each do |f|
|
168
|
+
chmod(mode, f.to_s)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
list
|
130
172
|
end
|
131
173
|
|
132
174
|
def touch(list, options={})
|
133
175
|
Array(list).each do |f|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
176
|
+
if fs = FileSystem.find(f)
|
177
|
+
now = Time.now
|
178
|
+
fs.mtime = now
|
179
|
+
fs.atime = now
|
138
180
|
else
|
139
|
-
|
181
|
+
f = File.open(f, 'w')
|
182
|
+
f.close
|
140
183
|
end
|
141
184
|
end
|
142
185
|
end
|