rubypath 0.3.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- metadata +5 -55
- data/CHANGELOG.md +0 -24
- data/LICENSE.txt +0 -165
- data/README.md +0 -102
- data/doc/file.README.html +0 -175
- data/lib/rubypath.rb +0 -29
- data/lib/rubypath/backend.rb +0 -92
- data/lib/rubypath/backend/mock.rb +0 -356
- data/lib/rubypath/backend/sys.rb +0 -161
- data/lib/rubypath/comparison.rb +0 -19
- data/lib/rubypath/construction.rb +0 -109
- data/lib/rubypath/dir_operations.rb +0 -160
- data/lib/rubypath/extensions.rb +0 -157
- data/lib/rubypath/file_operations.rb +0 -192
- data/lib/rubypath/file_predicates.rb +0 -32
- data/lib/rubypath/identity.rb +0 -59
- data/lib/rubypath/io_operations.rb +0 -82
- data/lib/rubypath/mock.rb +0 -42
- data/lib/rubypath/path_operations.rb +0 -311
- data/lib/rubypath/path_predicates.rb +0 -61
- data/lib/rubypath/version.rb +0 -11
- data/rubypath.gemspec +0 -22
- data/spec/README_spec.rb +0 -27
- data/spec/rubypath/comparison_spec.rb +0 -77
- data/spec/rubypath/construction_spec.rb +0 -101
- data/spec/rubypath/dir_operations_spec.rb +0 -225
- data/spec/rubypath/extensions_spec.rb +0 -270
- data/spec/rubypath/file_operations_spec.rb +0 -428
- data/spec/rubypath/file_predicates_spec.rb +0 -66
- data/spec/rubypath/identity_spec.rb +0 -21
- data/spec/rubypath/io_operations_spec.rb +0 -128
- data/spec/rubypath/path_operations_spec.rb +0 -483
- data/spec/rubypath/path_predicates_spec.rb +0 -75
- data/spec/spec_helper.rb +0 -42
- data/spec/support/describe_method.rb +0 -18
- data/spec/support/with_backend.rb +0 -37
data/lib/rubypath.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'rubypath/version'
|
2
|
-
require 'tmpdir'
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
class Path
|
8
|
-
require 'rubypath/identity'
|
9
|
-
require 'rubypath/construction'
|
10
|
-
require 'rubypath/comparison'
|
11
|
-
require 'rubypath/extensions'
|
12
|
-
|
13
|
-
require 'rubypath/path_operations'
|
14
|
-
require 'rubypath/path_predicates'
|
15
|
-
require 'rubypath/file_operations'
|
16
|
-
require 'rubypath/file_predicates'
|
17
|
-
require 'rubypath/dir_operations'
|
18
|
-
require 'rubypath/io_operations'
|
19
|
-
|
20
|
-
require 'rubypath/mock'
|
21
|
-
require 'rubypath/backend'
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
module Kernel
|
26
|
-
def Path(*args)
|
27
|
-
Path.new *args
|
28
|
-
end
|
29
|
-
end
|
data/lib/rubypath/backend.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
class Path
|
2
|
-
class Backend
|
3
|
-
class << self
|
4
|
-
def instance
|
5
|
-
@instance ||= new
|
6
|
-
end
|
7
|
-
|
8
|
-
def delegate(mth)
|
9
|
-
define_method mth do |*args|
|
10
|
-
backend.send mth, *args
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def mock(*args, &block)
|
15
|
-
self.instance.mock(*args, &block)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
attr_accessor :backend
|
20
|
-
def initialize
|
21
|
-
self.backend = Backend::Sys.new
|
22
|
-
end
|
23
|
-
|
24
|
-
def mock(opts = {}, &block)
|
25
|
-
if opts[:root]
|
26
|
-
# Use real file system scoped to given directory (chroot like)
|
27
|
-
if opts[:root] == :tmp
|
28
|
-
::Dir.mktmpdir('rubypath') do |path|
|
29
|
-
use_backend Backend::Sys.new(path), &block
|
30
|
-
end
|
31
|
-
else
|
32
|
-
use_backend Backend::Sys.new(opts[:root]), &block
|
33
|
-
end
|
34
|
-
else
|
35
|
-
# Use mock FS
|
36
|
-
use_backend Backend::Mock.new, &block
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def use_backend(be)
|
41
|
-
old_backend, self.backend = backend, be
|
42
|
-
yield
|
43
|
-
backend.quit if backend.respond_to? :quit
|
44
|
-
self.backend = old_backend
|
45
|
-
end
|
46
|
-
|
47
|
-
delegate :expand_path
|
48
|
-
delegate :getwd
|
49
|
-
delegate :exists?
|
50
|
-
delegate :mkdir
|
51
|
-
delegate :mkpath
|
52
|
-
delegate :directory?
|
53
|
-
delegate :file?
|
54
|
-
delegate :touch
|
55
|
-
delegate :write
|
56
|
-
delegate :read
|
57
|
-
delegate :mtime
|
58
|
-
delegate :mtime=
|
59
|
-
delegate :entries
|
60
|
-
delegate :glob
|
61
|
-
delegate :atime
|
62
|
-
delegate :atime=
|
63
|
-
delegate :get_umask
|
64
|
-
delegate :set_umask
|
65
|
-
delegate :mode
|
66
|
-
delegate :chmod
|
67
|
-
delegate :unlink
|
68
|
-
delegate :rmtree
|
69
|
-
delegate :rmtree!
|
70
|
-
delegate :safe_rmtree
|
71
|
-
delegate :safe_rmtree!
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
def invoke_backend(mth, *args)
|
77
|
-
args << self if args.empty?
|
78
|
-
self.class.send :invoke_backend, mth, *args
|
79
|
-
end
|
80
|
-
|
81
|
-
class << self
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
def invoke_backend(mth, *args)
|
86
|
-
Backend.instance.send mth, *args
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
require 'rubypath/backend/mock'
|
91
|
-
require 'rubypath/backend/sys'
|
92
|
-
end
|
@@ -1,356 +0,0 @@
|
|
1
|
-
class Path::Backend
|
2
|
-
|
3
|
-
class Mock
|
4
|
-
attr_reader :user, :homes
|
5
|
-
|
6
|
-
# @!group Virtual File System Configuration
|
7
|
-
|
8
|
-
# Set user that owns the current process.
|
9
|
-
def current_user=(user)
|
10
|
-
@user = user.to_s
|
11
|
-
end
|
12
|
-
|
13
|
-
# Define new home directories. Must be given as has a hash that is
|
14
|
-
# interpreted as a user name to home directory mapping.
|
15
|
-
attr_writer :homes
|
16
|
-
|
17
|
-
# Set current working directory.
|
18
|
-
attr_writer :cwd
|
19
|
-
|
20
|
-
# @!group Internal Methods
|
21
|
-
|
22
|
-
def initialize
|
23
|
-
@user = 'root'
|
24
|
-
@homes = {'root' => '/root'}
|
25
|
-
@cwd = '/root'
|
26
|
-
@umask = 0022
|
27
|
-
end
|
28
|
-
|
29
|
-
def home(user)
|
30
|
-
homes.fetch(user){ raise ArgumentError.new "user #{user} doesn't exist" }
|
31
|
-
end
|
32
|
-
|
33
|
-
# @!group Backend Operations
|
34
|
-
|
35
|
-
def expand_path(path, base = getwd)
|
36
|
-
if %r{^~(?<name>[^/]*)(/(?<rest>.*))?$} =~ path
|
37
|
-
::File.expand_path rest.to_s, home(name.empty? ? user : name)
|
38
|
-
else
|
39
|
-
::File.expand_path(path, base)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
alias_method :expand, :expand_path
|
43
|
-
|
44
|
-
def getwd
|
45
|
-
@cwd ||= '/'
|
46
|
-
end
|
47
|
-
|
48
|
-
def file?(path)
|
49
|
-
lookup(path).is_a?(File)
|
50
|
-
end
|
51
|
-
|
52
|
-
def directory?(path)
|
53
|
-
lookup(path).is_a?(Dir)
|
54
|
-
end
|
55
|
-
|
56
|
-
def exists?(path)
|
57
|
-
lookup(path) ? true : false
|
58
|
-
end
|
59
|
-
|
60
|
-
def mkdir(path)
|
61
|
-
return if path.to_s == '/'
|
62
|
-
|
63
|
-
node = lookup_parent! path
|
64
|
-
dir = node.lookup ::File.basename path
|
65
|
-
unless dir.is_a?(Dir)
|
66
|
-
if dir.nil?
|
67
|
-
node.add Dir.new(self, ::File.basename(path))
|
68
|
-
else
|
69
|
-
raise ArgumentError.new \
|
70
|
-
"Node #{dir.path} exists and is no directory."
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def mkpath(path)
|
76
|
-
path = expand_path(path)
|
77
|
-
::Pathname.new(path).descend do |p|
|
78
|
-
mkdir(p.to_s)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def touch(path)
|
83
|
-
node = lookup_parent! path
|
84
|
-
file = node.lookup ::File.basename path
|
85
|
-
if file
|
86
|
-
file.mtime = Time.now
|
87
|
-
else
|
88
|
-
node.add File.new(self, ::File.basename(path))
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def write(path, content, *args)
|
93
|
-
node = lookup_parent! path
|
94
|
-
file = node.lookup ::File.basename(path)
|
95
|
-
unless file
|
96
|
-
file = File.new self, ::File.basename(path)
|
97
|
-
node.add file
|
98
|
-
end
|
99
|
-
|
100
|
-
case file
|
101
|
-
when File
|
102
|
-
if args.empty?
|
103
|
-
file.content = content
|
104
|
-
else
|
105
|
-
offset = args[0].to_i
|
106
|
-
file.content[offset, content.length] = content
|
107
|
-
end
|
108
|
-
file.mtime = Time.now
|
109
|
-
when Dir
|
110
|
-
raise Errno::EISDIR.new path
|
111
|
-
else
|
112
|
-
raise ArgumentError.new
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def mtime(path)
|
117
|
-
lookup!(path).mtime
|
118
|
-
end
|
119
|
-
|
120
|
-
def mtime=(path, time)
|
121
|
-
lookup!(path).mtime = time
|
122
|
-
end
|
123
|
-
|
124
|
-
def atime(path)
|
125
|
-
lookup!(path).atime
|
126
|
-
end
|
127
|
-
|
128
|
-
def atime=(path, time)
|
129
|
-
lookup!(path).atime = time
|
130
|
-
end
|
131
|
-
|
132
|
-
def read(path, *args)
|
133
|
-
file = lookup_file!(path)
|
134
|
-
file.atime = Time.now
|
135
|
-
content = file.content
|
136
|
-
if args[0]
|
137
|
-
length = args[0].to_i
|
138
|
-
offset = args[1] ? args[1].to_i : 0
|
139
|
-
content = content.slice(offset, length)
|
140
|
-
end
|
141
|
-
content
|
142
|
-
end
|
143
|
-
|
144
|
-
def entries(path)
|
145
|
-
node = lookup_dir! path
|
146
|
-
node.children.map(&:name) + %w(. ..)
|
147
|
-
end
|
148
|
-
|
149
|
-
def glob(pattern, flags = 0, &block)
|
150
|
-
root.all.select do |node|
|
151
|
-
::File.fnmatch pattern, node.path, (flags | ::File::FNM_PATHNAME)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def get_umask
|
156
|
-
@umask
|
157
|
-
end
|
158
|
-
|
159
|
-
def set_umask(mask)
|
160
|
-
@umask = Integer(mask)
|
161
|
-
end
|
162
|
-
|
163
|
-
def mode(path)
|
164
|
-
lookup!(path).mode
|
165
|
-
end
|
166
|
-
|
167
|
-
def unlink(path)
|
168
|
-
node = lookup_parent!(path)
|
169
|
-
file = node.lookup ::File.basename path
|
170
|
-
case file
|
171
|
-
when Dir
|
172
|
-
raise Errno::EISDIR.new path
|
173
|
-
when File
|
174
|
-
node.children.delete(file)
|
175
|
-
when nil
|
176
|
-
raise Errno::ENOENT.new path
|
177
|
-
else
|
178
|
-
raise ArgumentError.new "Unknown node #{node.inspect} for #unlink."
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def rmtree(path)
|
183
|
-
node = lookup path
|
184
|
-
case node
|
185
|
-
when Dir, File
|
186
|
-
lookup_parent!(path).children.delete(node)
|
187
|
-
when nil
|
188
|
-
nil
|
189
|
-
else
|
190
|
-
raise ArgumentError.new "Unknown node #{node.inspect} for #rmtree."
|
191
|
-
end
|
192
|
-
end
|
193
|
-
alias_method :safe_rmtree, :rmtree
|
194
|
-
|
195
|
-
def rmtree!(path)
|
196
|
-
node = lookup path
|
197
|
-
case node
|
198
|
-
when Dir, File
|
199
|
-
lookup_parent!(path).children.delete(node)
|
200
|
-
when nil
|
201
|
-
raise Errno::ENOENT.new path
|
202
|
-
else
|
203
|
-
raise ArgumentError.new "Unknown node #{node.inspect} for #rmtree."
|
204
|
-
end
|
205
|
-
end
|
206
|
-
alias_method :safe_rmtree!, :rmtree!
|
207
|
-
|
208
|
-
# @!group Internal Virtual File System
|
209
|
-
|
210
|
-
# Return root node.
|
211
|
-
def root
|
212
|
-
@root ||= Dir.new(self, '')
|
213
|
-
end
|
214
|
-
|
215
|
-
def to_lookup(path)
|
216
|
-
path = expand path
|
217
|
-
path.sub(/^\/+/, '')
|
218
|
-
end
|
219
|
-
|
220
|
-
def lookup(path)
|
221
|
-
root.lookup to_lookup path
|
222
|
-
end
|
223
|
-
|
224
|
-
def lookup!(path)
|
225
|
-
if (node = lookup(path))
|
226
|
-
node
|
227
|
-
else
|
228
|
-
raise Errno::ENOENT.new path
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
def lookup_file!(path)
|
233
|
-
node = lookup! path
|
234
|
-
case node
|
235
|
-
when File
|
236
|
-
node
|
237
|
-
when Dir
|
238
|
-
raise Errno::EISDIR.new path
|
239
|
-
else
|
240
|
-
raise ArgumentError.new "NOT A FILE: #{path}"
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
def lookup_dir!(path)
|
245
|
-
if (node = lookup!(path)).is_a?(Dir)
|
246
|
-
node
|
247
|
-
else
|
248
|
-
raise Errno::ENOENT.new path
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
def lookup_parent!(path)
|
253
|
-
node = lookup ::File.dirname expand path
|
254
|
-
if node
|
255
|
-
node.is_a?(Dir) ? node : raise(Errno::ENOTDIR.new path)
|
256
|
-
else
|
257
|
-
raise Errno::ENOENT.new path
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
#
|
262
|
-
class Node
|
263
|
-
attr_reader :sys, :name, :parent
|
264
|
-
attr_accessor :mtime, :atime, :mode
|
265
|
-
|
266
|
-
def initialize(backend, name, ops = {})
|
267
|
-
@sys = backend
|
268
|
-
@name = name
|
269
|
-
@mtime = Time.now
|
270
|
-
@atime = Time.now
|
271
|
-
end
|
272
|
-
|
273
|
-
def mtime=(time)
|
274
|
-
if time.is_a?(Time)
|
275
|
-
@mtime = time
|
276
|
-
else
|
277
|
-
raise "Not Time but `#{time.inspect}` of `#{time.class.name}` given."
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
def lookup(path)
|
282
|
-
raise NotImplementError.new 'Subclass responsibility.'
|
283
|
-
end
|
284
|
-
|
285
|
-
def added(parent)
|
286
|
-
@parent = parent
|
287
|
-
end
|
288
|
-
|
289
|
-
def path
|
290
|
-
parent ? "#{parent.path}/#{name}" : name
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
#
|
295
|
-
class Dir < Node
|
296
|
-
def initialize(backend, name, opts = {})
|
297
|
-
super
|
298
|
-
self.mode = 0777 - backend.get_umask
|
299
|
-
end
|
300
|
-
|
301
|
-
def lookup(path)
|
302
|
-
name, rest = path.to_s.split('/', 2).map(&:to_s)
|
303
|
-
|
304
|
-
if name.nil?
|
305
|
-
if rest.nil?
|
306
|
-
self
|
307
|
-
else
|
308
|
-
lookup rest
|
309
|
-
end
|
310
|
-
else
|
311
|
-
child = children.find{|c| c.name == name }
|
312
|
-
if child
|
313
|
-
rest.nil? ? child : child.lookup(rest)
|
314
|
-
else
|
315
|
-
nil
|
316
|
-
end
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
def add(node)
|
321
|
-
if children.any?{|c| c.name == node.name }
|
322
|
-
raise ArgumentError.new "Node #{path}/#{node.name} already exists."
|
323
|
-
else
|
324
|
-
children << node
|
325
|
-
node.added self
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
def all
|
330
|
-
children.reduce([]) do |memo, child|
|
331
|
-
memo << child
|
332
|
-
memo += child.all if child.is_a?(Dir)
|
333
|
-
memo
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
def children
|
338
|
-
@children ||= []
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
#
|
343
|
-
class File < Node
|
344
|
-
attr_accessor :content
|
345
|
-
|
346
|
-
def initialize(backend, name, opts = {})
|
347
|
-
super
|
348
|
-
self.mode = 0666 - backend.get_umask
|
349
|
-
end
|
350
|
-
|
351
|
-
def lookup(path)
|
352
|
-
nil
|
353
|
-
end
|
354
|
-
end
|
355
|
-
end
|
356
|
-
end
|