pathname3 1.2.3
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/CHANGES +45 -0
- data/LICENSE +22 -0
- data/README +62 -0
- data/lib/pathname3.rb +573 -0
- data/pathname3.gemspec +31 -0
- data/test/lib/test_pathname.rb +486 -0
- data/test/lib/test_pathname3.rb +377 -0
- metadata +61 -0
data/CHANGES
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
= pathname3 Changelog
|
2
|
+
|
3
|
+
== Version 1.2.4
|
4
|
+
|
5
|
+
* Usage examples in the README
|
6
|
+
* Rakefile for docs/testing
|
7
|
+
* Fixes bugs where return values were not Pathnames
|
8
|
+
* Adds Pathname#glob
|
9
|
+
|
10
|
+
== Version 1.2.3
|
11
|
+
|
12
|
+
* Fixes gem building on GitHub
|
13
|
+
|
14
|
+
== Version 1.2.2
|
15
|
+
|
16
|
+
* Fixes a bug where split didn't return Pathnames
|
17
|
+
* Fixes a bug where empty components of a path were joined
|
18
|
+
* Fixes bugs where methods were called on the wrong class
|
19
|
+
* Documentation improvements
|
20
|
+
|
21
|
+
== Version 1.2.1
|
22
|
+
|
23
|
+
* Fix a bug where Pathname#open was accidentally redefined due to misnamed
|
24
|
+
method
|
25
|
+
|
26
|
+
== Version 1.2.0
|
27
|
+
|
28
|
+
* == compares paths semantically
|
29
|
+
* Better compatibility with Pathname
|
30
|
+
* Full documentation
|
31
|
+
|
32
|
+
== Version 1.1.0
|
33
|
+
|
34
|
+
* More compliant with original Pathname.
|
35
|
+
* Specs testing compliance from Rubinius
|
36
|
+
|
37
|
+
== Version 1.0.1
|
38
|
+
|
39
|
+
* Included the MIT license. Whoops.
|
40
|
+
|
41
|
+
== Version 1.0.0
|
42
|
+
|
43
|
+
* First release
|
44
|
+
* Mostly-compatible support with pathname
|
45
|
+
* String-based pathname implementation
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Stephen Touset
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
= pathname3
|
2
|
+
|
3
|
+
This library is a replacement for the venerable pathname and pathname2
|
4
|
+
libraries.
|
5
|
+
|
6
|
+
The original implementation of pathname is extremely slow, and
|
7
|
+
instantiates extreme numbers of objects for relatively simple operations.
|
8
|
+
Twenty or so Pathname instantiations on some method calls is relatively
|
9
|
+
common.
|
10
|
+
|
11
|
+
An implementation by Daniel J. Berger, pathname2, improved on the original
|
12
|
+
significantly, adding Windows support, a Facade implementation, and a String-
|
13
|
+
based implementation. While his version is faster, it's still very slow at
|
14
|
+
instantiation. And it's Facade implementation misses some odd case methods
|
15
|
+
like Pathname#join.
|
16
|
+
|
17
|
+
This version will focus on being fast and lightweight, while still being pure
|
18
|
+
Ruby. Windows support will be forthcoming once I have access to a Windows
|
19
|
+
development machine. Until then, patches adding Windows compatibility are
|
20
|
+
welcome.
|
21
|
+
|
22
|
+
== Installation
|
23
|
+
|
24
|
+
You can install pathname3 through Rubygems. The gem is hosted on GitHub, and
|
25
|
+
can be installed via
|
26
|
+
|
27
|
+
$ sudo gem install --source http://gems.github.com/ stouset-pathname3
|
28
|
+
|
29
|
+
== Usage
|
30
|
+
|
31
|
+
require 'pathname3'
|
32
|
+
|
33
|
+
p = '~/foo'.to_path # => "~/foo"
|
34
|
+
p.absolute? # => false
|
35
|
+
p.relative? # => true
|
36
|
+
p.exists? # => false
|
37
|
+
|
38
|
+
p = p.absolute # => "/Users/stouset/foo"
|
39
|
+
p.absolute? # => true
|
40
|
+
p.relative? # => false
|
41
|
+
p.relative_path_from('/Users') # => "stouset/foo"
|
42
|
+
p.relative_path_from('/Library') # => "../Users/stouset/foo"
|
43
|
+
p.split # => ["/Users/stouset", "foo"]
|
44
|
+
p.touch # => "/Users/stouset/foo"
|
45
|
+
p.ctime # => Thu Jun 05 14:00:01 -0400 2008
|
46
|
+
p.delete # => true
|
47
|
+
|
48
|
+
== Contribution
|
49
|
+
|
50
|
+
The pathname3 project is hosted on GitHub.
|
51
|
+
|
52
|
+
http://github.com/stouset/pathname3/
|
53
|
+
|
54
|
+
To clone the repository, simply run:
|
55
|
+
|
56
|
+
git clone git://github.com/stouset/pathname3.git
|
57
|
+
|
58
|
+
== License
|
59
|
+
|
60
|
+
pathname3 is available under the MIT license.
|
61
|
+
|
62
|
+
:include: LICENSE
|
data/lib/pathname3.rb
ADDED
@@ -0,0 +1,573 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'find'
|
3
|
+
|
4
|
+
#
|
5
|
+
# Pathname represents a path to a file on a filesystem. It can be relative or
|
6
|
+
# absolute. It exists to provide a more instance-oriented approach to managing
|
7
|
+
# paths than the class-level methods on File, FileTest, Dir, and Find.
|
8
|
+
#
|
9
|
+
class Pathname < String
|
10
|
+
SYMLOOP_MAX = 8 # deepest symlink traversal
|
11
|
+
|
12
|
+
ROOT = '/'.freeze
|
13
|
+
DOT = '.'.freeze
|
14
|
+
DOT_DOT = '..'.freeze
|
15
|
+
|
16
|
+
#
|
17
|
+
# Creates a new Pathname. Any path with a null is rejected.
|
18
|
+
#
|
19
|
+
def initialize(path)
|
20
|
+
if path =~ %r{\0}
|
21
|
+
raise ArgumentError, "path cannot contain ASCII NULLs"
|
22
|
+
end
|
23
|
+
|
24
|
+
super(path)
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Compares pathnames, case-sensitively. Sorts directories higher than other
|
29
|
+
# files named similarly.
|
30
|
+
#
|
31
|
+
def <=>(other)
|
32
|
+
self.tr('/', "\0").to_s <=> other.to_str.tr('/', "\0")
|
33
|
+
rescue NoMethodError # doesn't respond to to_str
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Compares two pathnames for equality. Considers pathnames equal if they
|
39
|
+
# both point to the same location, and are both absolute or both relative.
|
40
|
+
#
|
41
|
+
def ==(other)
|
42
|
+
left = self.cleanpath.tr('/', "\0").to_s
|
43
|
+
right = other.to_str.to_path.cleanpath.tr('/', "\0").to_s
|
44
|
+
|
45
|
+
left == right
|
46
|
+
rescue NoMethodError # doesn't implement to_str
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Appends a component of a path to self. Returns a Pathname to the combined
|
52
|
+
# path. Cleans any redundant components of the path.
|
53
|
+
#
|
54
|
+
def +(path)
|
55
|
+
dup << path
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Appends (destructively) a component of a path to self. Replaces the
|
60
|
+
# contents of the current Pathname with the new, combined path. Cleans any
|
61
|
+
# redundant components of the path.
|
62
|
+
#
|
63
|
+
def <<(path)
|
64
|
+
replace( join(path).cleanpath! )
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Returns true if this is an absolute path.
|
69
|
+
#
|
70
|
+
def absolute?
|
71
|
+
self[0, 1].to_s == ROOT
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Yields to each component of the path, going up to the root.
|
76
|
+
#
|
77
|
+
# Pathname.new('/path/to/some/file').ascend {|path| p path }
|
78
|
+
# "/path/to/some/file"
|
79
|
+
# "/path/to/some"
|
80
|
+
# "/path/to"
|
81
|
+
# "/path"
|
82
|
+
# "/"
|
83
|
+
#
|
84
|
+
# Pathname.new('a/relative/path').ascend {|path| p path }
|
85
|
+
# "a/relative/path"
|
86
|
+
# "a/relative"
|
87
|
+
# "a"
|
88
|
+
#
|
89
|
+
# Does not actually access the filesystem.
|
90
|
+
#
|
91
|
+
def ascend
|
92
|
+
parts = to_a
|
93
|
+
parts.length.downto(1) do |i|
|
94
|
+
yield self.class.join(parts[0, i])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# Returns all children of this path. "." and ".." are not included, since
|
100
|
+
# they aren't under the current path.
|
101
|
+
#
|
102
|
+
def children
|
103
|
+
entries[2..-1]
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Cleans the path by removing consecutive slashes, and useless dots.
|
108
|
+
# Replaces the contents of the current Pathname.
|
109
|
+
#
|
110
|
+
def cleanpath!
|
111
|
+
parts = to_a
|
112
|
+
final = []
|
113
|
+
|
114
|
+
parts.each do |part|
|
115
|
+
case part
|
116
|
+
when DOT then next
|
117
|
+
when DOT_DOT then
|
118
|
+
case final.last
|
119
|
+
when ROOT then next
|
120
|
+
when DOT_DOT then final.push(DOT_DOT)
|
121
|
+
when nil then final.push(DOT_DOT)
|
122
|
+
else final.pop
|
123
|
+
end
|
124
|
+
else final.push(part)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
replace(final.empty? ? DOT : self.class.join(*final))
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Cleans the path by removing consecutive slashes, and useless dots.
|
133
|
+
#
|
134
|
+
def cleanpath
|
135
|
+
dup.cleanpath!
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Yields to each component of the path, going down from the root.
|
140
|
+
#
|
141
|
+
# Pathname.new('/path/to/some/file').ascend {|path| p path }
|
142
|
+
# "/"
|
143
|
+
# "/path"
|
144
|
+
# "/path/to"
|
145
|
+
# "/path/to/some"
|
146
|
+
# "/path/to/some/file"
|
147
|
+
#
|
148
|
+
# Pathname.new('a/relative/path').ascend {|path| p path }
|
149
|
+
# "a"
|
150
|
+
# "a/relative"
|
151
|
+
# "a/relative/path"
|
152
|
+
#
|
153
|
+
# Does not actually access the filesystem.
|
154
|
+
#
|
155
|
+
def descend
|
156
|
+
parts = to_a
|
157
|
+
1.upto(parts.length) do |i|
|
158
|
+
yield self.class.join(parts[0, i])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Returns true if this path is simply a '.'.
|
164
|
+
#
|
165
|
+
def dot?
|
166
|
+
self == DOT
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# Returns true if this path is simply a '..'.
|
171
|
+
#
|
172
|
+
def dot_dot?
|
173
|
+
self == DOT_DOT
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Iterates over every component of the path.
|
178
|
+
#
|
179
|
+
# Pathname.new('/path/to/some/file').ascend {|path| p path }
|
180
|
+
# "/"
|
181
|
+
# "path"
|
182
|
+
# "to"
|
183
|
+
# "some"
|
184
|
+
# "file"
|
185
|
+
#
|
186
|
+
# Pathname.new('a/relative/path').each_filename {|part| p part }
|
187
|
+
# "a"
|
188
|
+
# "relative"
|
189
|
+
# "path"
|
190
|
+
#
|
191
|
+
def each_filename(&blk)
|
192
|
+
to_a.each(&blk)
|
193
|
+
end
|
194
|
+
|
195
|
+
#
|
196
|
+
# Returns true if the path is a mountpoint.
|
197
|
+
#
|
198
|
+
def mountpoint?
|
199
|
+
stat1 = self.lstat
|
200
|
+
stat2 = self.parent.lstat
|
201
|
+
|
202
|
+
stat1.dev != stat2.dev || stat1.ino == stat2.ino
|
203
|
+
rescue Errno::ENOENT
|
204
|
+
false
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
# Returns a path to the parent directory. Simply appends a "..".
|
209
|
+
#
|
210
|
+
def parent
|
211
|
+
self + '..'
|
212
|
+
end
|
213
|
+
|
214
|
+
#
|
215
|
+
# Resolves a path to locate a real location on the filesystem. Resolves
|
216
|
+
# symlinks up to a deptho of SYMLOOP_MAX.
|
217
|
+
#
|
218
|
+
def realpath
|
219
|
+
path = self
|
220
|
+
|
221
|
+
SYMLOOP_MAX.times do
|
222
|
+
link = path.readlink
|
223
|
+
link = path.dirname + link if link.relative?
|
224
|
+
path = link
|
225
|
+
end
|
226
|
+
|
227
|
+
raise Errno::ELOOP, self
|
228
|
+
rescue Errno::EINVAL
|
229
|
+
path.expand_path
|
230
|
+
end
|
231
|
+
|
232
|
+
#
|
233
|
+
# Returns true if this is a relative path.
|
234
|
+
#
|
235
|
+
def relative?
|
236
|
+
!absolute?
|
237
|
+
end
|
238
|
+
|
239
|
+
#
|
240
|
+
# Returns this path as a relative location from +base+. The path and +base+
|
241
|
+
# must both be relative or both be absolute. An ArgumentError is raised if
|
242
|
+
# a relative path can't be generated between the two locations.
|
243
|
+
#
|
244
|
+
# Does not access the filesystem.
|
245
|
+
#
|
246
|
+
def relative_path_from(base)
|
247
|
+
base = base.to_path
|
248
|
+
|
249
|
+
# both must be relative, or both must be absolute
|
250
|
+
if self.absolute? != base.absolute?
|
251
|
+
raise ArgumentError, 'no relative path between a relative and absolute'
|
252
|
+
end
|
253
|
+
|
254
|
+
return self if base.dot?
|
255
|
+
return DOT.to_path if self == base
|
256
|
+
|
257
|
+
base = base.cleanpath.to_a
|
258
|
+
dest = self.cleanpath.to_a
|
259
|
+
|
260
|
+
while !dest.empty? && !base.empty? && dest[0] == base[0]
|
261
|
+
base.shift
|
262
|
+
dest.shift
|
263
|
+
end
|
264
|
+
|
265
|
+
base.shift if base[0] == DOT
|
266
|
+
dest.shift if dest[0] == DOT
|
267
|
+
|
268
|
+
if base.include?(DOT_DOT)
|
269
|
+
raise ArgumentError, "base directory may not contain '#{DOT_DOT}'"
|
270
|
+
end
|
271
|
+
|
272
|
+
path = base.fill(DOT_DOT) + dest
|
273
|
+
path = self.class.join(*path)
|
274
|
+
path = DOT.to_path if path.empty?
|
275
|
+
|
276
|
+
path
|
277
|
+
end
|
278
|
+
|
279
|
+
#
|
280
|
+
# Returns true if this path points to the root of the filesystem.
|
281
|
+
#
|
282
|
+
def root?
|
283
|
+
!!(self =~ %r{^#{ROOT}+$})
|
284
|
+
end
|
285
|
+
|
286
|
+
#
|
287
|
+
# Splits the path into an array of its components.
|
288
|
+
#
|
289
|
+
def to_a
|
290
|
+
array = to_s.split(File::SEPARATOR)
|
291
|
+
array.delete('')
|
292
|
+
array.insert(0, ROOT) if absolute?
|
293
|
+
array
|
294
|
+
end
|
295
|
+
|
296
|
+
#
|
297
|
+
# Returns self.
|
298
|
+
#
|
299
|
+
def to_path
|
300
|
+
self
|
301
|
+
end
|
302
|
+
|
303
|
+
#
|
304
|
+
# Unlinks the file or directory at the path.
|
305
|
+
#
|
306
|
+
def unlink
|
307
|
+
Dir.unlink(self)
|
308
|
+
true
|
309
|
+
rescue Errno::ENOTDIR
|
310
|
+
File.unlink(self)
|
311
|
+
true
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
class Pathname
|
316
|
+
# See Dir::[]
|
317
|
+
def self.[](pattern); Dir[pattern].map! {|d| d.to_path }; end
|
318
|
+
|
319
|
+
# See Dir::pwd
|
320
|
+
def self.pwd; Dir.pwd.to_path; end
|
321
|
+
|
322
|
+
# See Dir::entries
|
323
|
+
def entries; Dir.entries(self).map! {|e| e.to_path }; end
|
324
|
+
|
325
|
+
# See Dir::mkdir
|
326
|
+
def mkdir(mode = 0777); Dir.mkdir(self, mode); end
|
327
|
+
|
328
|
+
# See Dir::open
|
329
|
+
def opendir(&blk); Dir.open(self, &blk); end
|
330
|
+
|
331
|
+
# See Dir::rmdir
|
332
|
+
def rmdir; Dir.rmdir(self); end
|
333
|
+
|
334
|
+
# See Dir::glob
|
335
|
+
def self.glob(pattern, flags = 0)
|
336
|
+
dirs = Dir.glob(pattern, flags)
|
337
|
+
dirs.map! {|path| path.to_path }
|
338
|
+
|
339
|
+
if block_given?
|
340
|
+
dirs.each {|dir| yield dir }
|
341
|
+
nil
|
342
|
+
else
|
343
|
+
dirs
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
# See Dir::glob
|
348
|
+
def glob(pattern, flags = 0, &block)
|
349
|
+
patterns = [pattern].flatten
|
350
|
+
patterns.map! {|p| self.class.glob(self.to_s + p, flags, &block) }
|
351
|
+
patterns.flatten
|
352
|
+
end
|
353
|
+
|
354
|
+
# See Dir::chdir
|
355
|
+
def chdir
|
356
|
+
blk = lambda { yield self } if block_given?
|
357
|
+
Dir.chdir(self, &blk)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
class Pathname
|
362
|
+
# See FileTest::blockdev?
|
363
|
+
def blockdev?; FileTest.blockdev?(self); end
|
364
|
+
|
365
|
+
# See FileTest::chardev?
|
366
|
+
def chardev?; FileTest.chardev?(self); end
|
367
|
+
|
368
|
+
# See FileTest::directory?
|
369
|
+
def directory?; FileTest.directory?(self); end
|
370
|
+
|
371
|
+
# See FileTest::executable?
|
372
|
+
def executable?; FileTest.executable?(self); end
|
373
|
+
|
374
|
+
# See FileTest::executable_real?
|
375
|
+
def executable_real?; FileTest.executable_real?(self); end
|
376
|
+
|
377
|
+
# See FileTest::exists?
|
378
|
+
def exists?; FileTest.exists?(self); end
|
379
|
+
|
380
|
+
# See FileTest::file?
|
381
|
+
def file?; FileTest.file?(self); end
|
382
|
+
|
383
|
+
# See FileTest::grpowned?
|
384
|
+
def grpowned?; FileTest.grpowned?(self); end
|
385
|
+
|
386
|
+
# See FileTest::owned?
|
387
|
+
def owned?; FileTest.owned?(self); end
|
388
|
+
|
389
|
+
# See FileTest::pipe?
|
390
|
+
def pipe?; FileTest.pipe?(self); end
|
391
|
+
|
392
|
+
# See FileTest::readable?
|
393
|
+
def readable?; FileTest.readable?(self); end
|
394
|
+
|
395
|
+
# See FileTest::readable_real?
|
396
|
+
def readable_real?; FileTest.readable_real?(self); end
|
397
|
+
|
398
|
+
# See FileTest::setgid?
|
399
|
+
def setgid?; FileTest.setgit?(self); end
|
400
|
+
|
401
|
+
# See FileTest::setuid?
|
402
|
+
def setuid?; FileTest.setuid?(self); end
|
403
|
+
|
404
|
+
# See FileTest::socket?
|
405
|
+
def socket?; FileTest.socket?(self); end
|
406
|
+
|
407
|
+
# See FileTest::sticky?
|
408
|
+
def sticky?; FileTest.sticky?(self); end
|
409
|
+
|
410
|
+
# See FileTest::symlink?
|
411
|
+
def symlink?; FileTest.symlink?(self); end
|
412
|
+
|
413
|
+
# See FileTest::world_readable?
|
414
|
+
def world_readable?; FileTest.world_readable?(self); end
|
415
|
+
|
416
|
+
# See FileTest::world_writable?
|
417
|
+
def world_writable?; FileTest.world_writable?(self); end
|
418
|
+
|
419
|
+
# See FileTest::writable?
|
420
|
+
def writable?; FileTest.writable?(self); end
|
421
|
+
|
422
|
+
# See FileTest::writable_real?
|
423
|
+
def writable_real?; FileTest.writable_real?(self); end
|
424
|
+
|
425
|
+
# See FileTest::zero?
|
426
|
+
def zero?; FileTest.zero?(self); end
|
427
|
+
end
|
428
|
+
|
429
|
+
class Pathname
|
430
|
+
# See File::atime
|
431
|
+
def atime; File.atime(self); end
|
432
|
+
|
433
|
+
# See File::ctime
|
434
|
+
def ctime; File.ctime(self); end
|
435
|
+
|
436
|
+
# See File::ftype
|
437
|
+
def ftype; File.ftype(self); end
|
438
|
+
|
439
|
+
# See File::lstat
|
440
|
+
def lstat; File.lstat(self); end
|
441
|
+
|
442
|
+
# See File::mtime
|
443
|
+
def mtime; File.mtime(self); end
|
444
|
+
|
445
|
+
# See File::stat
|
446
|
+
def stat; File.stat(self); end
|
447
|
+
|
448
|
+
# See File::utime
|
449
|
+
def utime(atime, mtime); File.utime(self, atime, mtime); end
|
450
|
+
end
|
451
|
+
|
452
|
+
class Pathname
|
453
|
+
# See File::join
|
454
|
+
def self.join(*parts); File.join(*parts.reject {|p| p.empty? }).to_path; end
|
455
|
+
|
456
|
+
# See File::basename
|
457
|
+
def basename; File.basename(self).to_path; end
|
458
|
+
|
459
|
+
# See File::chmod
|
460
|
+
def chmod(mode); File.chmod(mode, self); end
|
461
|
+
|
462
|
+
# See File::chown
|
463
|
+
def chown(owner, group); File.chown(owner, group, self); end
|
464
|
+
|
465
|
+
# See File::dirname
|
466
|
+
def dirname; File.dirname(self).to_path; end
|
467
|
+
|
468
|
+
# See File::expand_path
|
469
|
+
def expand_path(from = nil); File.expand_path(self, from).to_path; end
|
470
|
+
|
471
|
+
# See File::extname
|
472
|
+
def extname; File.extname(self); end
|
473
|
+
|
474
|
+
# See File::fnmatch
|
475
|
+
def fnmatch?(pat, flags = 0); File.fnmatch(pat, self, flags); end
|
476
|
+
|
477
|
+
# See File::join
|
478
|
+
def join(*parts); self.class.join(self, *parts); end
|
479
|
+
|
480
|
+
# See File::lchmod
|
481
|
+
def lchmod(mode); File.lchmod(mode, self); end
|
482
|
+
|
483
|
+
# See File::lchown
|
484
|
+
def lchown(owner, group); File.lchown(owner, group, self); end
|
485
|
+
|
486
|
+
# See File::link
|
487
|
+
def link(to); File.link(self, to); end
|
488
|
+
|
489
|
+
# See File::open
|
490
|
+
def open(mode = 'r', perm = nil, &blk); File.open(self, mode, perm, &blk); end
|
491
|
+
|
492
|
+
# See File::readlink
|
493
|
+
def readlink; File.readlink(self).to_path; end
|
494
|
+
|
495
|
+
# See File::rename
|
496
|
+
def rename(to); File.rename(self, to); replace(to); end
|
497
|
+
|
498
|
+
# See File::size
|
499
|
+
def size; File.size(self); end
|
500
|
+
|
501
|
+
# See File::size?
|
502
|
+
def size?; File.size?(self); end
|
503
|
+
|
504
|
+
# See File::split
|
505
|
+
def split; File.split(self).map {|part| part.to_path }; end
|
506
|
+
|
507
|
+
# See File::symlink
|
508
|
+
def symlink(to); File.symlink(self, to); end
|
509
|
+
|
510
|
+
# See File::truncate
|
511
|
+
def truncate; File.truncate(self); end
|
512
|
+
end
|
513
|
+
|
514
|
+
class Pathname
|
515
|
+
# See FileUtils::mkpath
|
516
|
+
def mkpath; FileUtils.mkpath(self).to_path; end
|
517
|
+
|
518
|
+
# See FileUtils::rmtree
|
519
|
+
def rmtree; FileUtils.rmtree(self).first.to_path; end
|
520
|
+
|
521
|
+
# See FileUtils::touch
|
522
|
+
def touch; FileUtils.touch(self).first.to_path; end
|
523
|
+
end
|
524
|
+
|
525
|
+
class Pathname
|
526
|
+
# See IO::each_line
|
527
|
+
def each_line(sep = $/, &blk); IO.foreach(self, sep, &blk); end
|
528
|
+
|
529
|
+
# See IO::read
|
530
|
+
def read(len = nil, off = 0); IO.read(self, len, off); end
|
531
|
+
|
532
|
+
# See IO::readlines
|
533
|
+
def readlines(sep = $/); IO.readlines(self, sep); end
|
534
|
+
|
535
|
+
# See IO::sysopen
|
536
|
+
def sysopen(mode = 'r', perm = nil); IO.sysopen(self, mode, perm); end
|
537
|
+
end
|
538
|
+
|
539
|
+
class Pathname
|
540
|
+
# See Find::find
|
541
|
+
def find; Find.find(self) {|path| yield path.to_path }; end
|
542
|
+
end
|
543
|
+
|
544
|
+
class Pathname
|
545
|
+
class << self
|
546
|
+
alias getwd pwd
|
547
|
+
end
|
548
|
+
|
549
|
+
alias absolute expand_path
|
550
|
+
alias delete unlink
|
551
|
+
alias exist? exists?
|
552
|
+
alias fnmatch fnmatch?
|
553
|
+
end
|
554
|
+
|
555
|
+
class String
|
556
|
+
#
|
557
|
+
# Converts the string directly to a pathname.
|
558
|
+
#
|
559
|
+
def to_path
|
560
|
+
Pathname.new(self)
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
module Kernel
|
565
|
+
#
|
566
|
+
# Allows construction of a Pathname by using the class name as a method.
|
567
|
+
#
|
568
|
+
# This really ought to be deprecated due to String#to_path.
|
569
|
+
#
|
570
|
+
def Pathname(path)
|
571
|
+
Pathname.new(path)
|
572
|
+
end
|
573
|
+
end
|