pathname2 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +2 -0
- data/MANIFEST +10 -0
- data/README +90 -0
- data/lib/pathname2.rb +536 -0
- data/test/tc_pathname.rb +182 -0
- data/test/tc_pathname_win.rb +227 -0
- metadata +55 -0
data/CHANGES
ADDED
data/MANIFEST
ADDED
data/README
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
== Description
|
2
|
+
A drop in replacement for the current Pathname class.
|
3
|
+
|
4
|
+
== Prerequisites
|
5
|
+
* Ruby 1.8.0 or later
|
6
|
+
* facade 1.0.0 or later (available on the RAA)
|
7
|
+
|
8
|
+
== Installation
|
9
|
+
=== Manual Installation
|
10
|
+
ruby test/tc_pathname.rb (Unix, optional)
|
11
|
+
ruby test/tc_pathname_win.rb (Windows, optional)
|
12
|
+
ruby install.rb
|
13
|
+
|
14
|
+
=== Gem Installation
|
15
|
+
ruby test/tc_pathname.rb (Unix, optional)
|
16
|
+
ruby test/tc_pathname_win.rb (Windows, optional)
|
17
|
+
gem install pathname2-<version>.gem
|
18
|
+
|
19
|
+
== Synopsis
|
20
|
+
require "pathname"
|
21
|
+
|
22
|
+
# Unix
|
23
|
+
path1 = "/foo/bar/baz"
|
24
|
+
path2 = "../zap"
|
25
|
+
|
26
|
+
path1 + path2 # "/foo/bar/zap"
|
27
|
+
path1.exists? # Does this path exist?
|
28
|
+
path1.dirname # "/foo/bar"
|
29
|
+
path1.to_a # ['foo','bar','baz']
|
30
|
+
|
31
|
+
# Win32
|
32
|
+
path1 = "C:/foo/bar/baz"
|
33
|
+
path2 = "../zap"
|
34
|
+
|
35
|
+
path1 + path2 # "C:\\foo\\bar\\zap"
|
36
|
+
path1.root # "C:\\"
|
37
|
+
path1.to_a # ['C:','foo','bar','baz']
|
38
|
+
|
39
|
+
== Win32 Notes
|
40
|
+
All forward slashes are converted to backslashes for Pathname objects.
|
41
|
+
|
42
|
+
== Differences between Unix and Win32
|
43
|
+
If your pathname consists solely of ".", or "..", the return
|
44
|
+
value for Pathname#clean will be different. On Win32, "\\" is returned,
|
45
|
+
while on Unix "." is returned. I consider this an extreme edge case and
|
46
|
+
will not worry myself with it.
|
47
|
+
|
48
|
+
== Differences between the old version and this version
|
49
|
+
* It is a subclass of String (and thus, mixes in Enumerable).
|
50
|
+
* It has sensical to_a and root instance methods.
|
51
|
+
* It works on Windows and Unix. The current implementation does not work
|
52
|
+
with Windows path names very well, and not at all when it comes to UNC
|
53
|
+
paths.
|
54
|
+
* The Pathname#cleanpath method works differently - it always returns
|
55
|
+
a canonical pathname. In addition, there is no special consideration
|
56
|
+
for symlinks (yet).
|
57
|
+
* The Pathname#+ method auto cleans.
|
58
|
+
* It uses a facade for all File and Dir methods, as well as all ftools
|
59
|
+
methods and most FileUtils methods.
|
60
|
+
|
61
|
+
== Method Priority
|
62
|
+
Because there is some overlap in method names between File, Dir, ftools
|
63
|
+
and FileUtils, the priority is as follows:
|
64
|
+
|
65
|
+
* File
|
66
|
+
* Dir
|
67
|
+
* ftools
|
68
|
+
* FileUtils
|
69
|
+
|
70
|
+
In other words, whichever of these defines a given method first is the
|
71
|
+
method that is used by the pathname2 package. For example, the
|
72
|
+
Pathname#safe_unlink method used is the one defined in ftools.rb,
|
73
|
+
not the one defined in the FileUtils module.
|
74
|
+
|
75
|
+
== Known Issues
|
76
|
+
You cannot pass a frozen string to the constructor on Win32 systems.
|
77
|
+
There is an unresolved issue with Win32API and frozen objects.
|
78
|
+
|
79
|
+
== License
|
80
|
+
Ruby's
|
81
|
+
|
82
|
+
== Warranty
|
83
|
+
This package is provided "as is" and without any express or
|
84
|
+
implied warranties, including, without limitation, the implied
|
85
|
+
warranties of merchantability and fitness for a particular purpose.
|
86
|
+
|
87
|
+
== Author
|
88
|
+
Daniel J. Berger
|
89
|
+
djberg96 at gmail dot com
|
90
|
+
imperator on IRC (irc.freenode.net)
|
data/lib/pathname2.rb
ADDED
@@ -0,0 +1,536 @@
|
|
1
|
+
# == Synopsis
|
2
|
+
#
|
3
|
+
# Pathname represents a path name on a filesystem. A Pathname can be
|
4
|
+
# relative or absolute. It does not matter whether the path exists or not.
|
5
|
+
#
|
6
|
+
# All functionality from File, FileTest, and Dir is included, using a facade
|
7
|
+
# pattern.
|
8
|
+
#
|
9
|
+
# This class works on both Unix and Win32, including UNC path names. Note
|
10
|
+
# that forward slashes are converted to backslashes on Win32 systems.
|
11
|
+
#
|
12
|
+
# == Usage
|
13
|
+
#
|
14
|
+
# require "pathname"
|
15
|
+
#
|
16
|
+
# # Unix
|
17
|
+
# path1 = Pathname.new("/foo/bar/baz")
|
18
|
+
# path2 = Pathname.new("../zap")
|
19
|
+
#
|
20
|
+
# path1 + path2 # "/foo/bar/zap"
|
21
|
+
# path1.dirname # "/foo/bar"
|
22
|
+
#
|
23
|
+
# # Win32
|
24
|
+
# path1 = Pathname.new("C:\\foo\\bar\\baz")
|
25
|
+
# path2 = Pathname.new("..\\zap")
|
26
|
+
#
|
27
|
+
# path1 + path2 # "C:\\foo\\bar\\zap"
|
28
|
+
# path1.exists? # Does the path exist?
|
29
|
+
#
|
30
|
+
# == Author
|
31
|
+
#
|
32
|
+
# Daniel J. Berger
|
33
|
+
# djberg96 at gmail dot com
|
34
|
+
# imperator on IRC (irc.freenode.net)
|
35
|
+
#
|
36
|
+
# == Copyright
|
37
|
+
# Copyright (c) 2005 Daniel J. Berger.
|
38
|
+
# Licensed under the same terms as Ruby itself.
|
39
|
+
#
|
40
|
+
require "facade"
|
41
|
+
require "ftools"
|
42
|
+
require "fileutils"
|
43
|
+
|
44
|
+
class Pathname < String
|
45
|
+
extend Facade
|
46
|
+
facade File
|
47
|
+
facade Dir
|
48
|
+
|
49
|
+
if PLATFORM.match("mswin32")
|
50
|
+
require "Win32API"
|
51
|
+
@@PathStripToRoot = Win32API.new("shlwapi","PathStripToRoot","P","L")
|
52
|
+
@@PathIsUNC = Win32API.new("shlwapi","PathIsUNC","P","L")
|
53
|
+
@@PathIsURL = Win32API.new("shlwapi","PathIsURL","P","L")
|
54
|
+
@@PathCanonicalize = Win32API.new("shlwapi","PathCanonicalize","PP","L")
|
55
|
+
@@PathAppend = Win32API.new("shlwapi","PathAppend","PP","L")
|
56
|
+
@@PathIsRoot = Win32API.new("shlwapi","PathIsRoot","P","L")
|
57
|
+
@@PathIsDirectory = Win32API.new("shlwapi","PathIsDirectory","P","L")
|
58
|
+
@@PathIsRelative = Win32API.new("shlwapi","PathIsRelative","P","L")
|
59
|
+
@@PathFileExists = Win32API.new("shlwapi","PathFileExists","P","L")
|
60
|
+
@@PathUndecorate = Win32API.new("shlwapi","PathUndecorate","P","L")
|
61
|
+
|
62
|
+
@@PathGetDriveNumber =
|
63
|
+
Win32API.new("shlwapi","PathGetDriveNumber","P","L")
|
64
|
+
|
65
|
+
@@PathCreateFromUrl =
|
66
|
+
Win32API.new("shlwapi", "PathCreateFromUrl", "PPPL", "L")
|
67
|
+
|
68
|
+
@@PathRemoveBackslash =
|
69
|
+
Win32API.new("shlwapi", "PathRemoveBackslash", "P", "P")
|
70
|
+
end
|
71
|
+
|
72
|
+
VERSION = "1.0.0"
|
73
|
+
MAX_PATH = 260
|
74
|
+
|
75
|
+
# Creates and returns a new Pathname object.
|
76
|
+
#
|
77
|
+
# On Win32 systems, all forward slashes are replaced with backslashes.
|
78
|
+
def initialize(path)
|
79
|
+
if path.length > MAX_PATH
|
80
|
+
msg = "string too long. maximum string length is " + MAX_PATH.to_s
|
81
|
+
raise PathnameError, msg
|
82
|
+
end
|
83
|
+
|
84
|
+
@sep = File::ALT_SEPARATOR || File::SEPARATOR
|
85
|
+
@win32 = PLATFORM.match("mswin32")
|
86
|
+
|
87
|
+
# Handle File URL's for Windows
|
88
|
+
if @win32
|
89
|
+
if @@PathIsURL.call(path) > 0
|
90
|
+
buf = 0.chr * MAX_PATH
|
91
|
+
len = [buf.length].pack("l")
|
92
|
+
if @@PathCreateFromUrl.call(path, buf, len, 0) >= 0
|
93
|
+
path = buf.strip
|
94
|
+
else
|
95
|
+
raise PathnameError, "invalid file url: #{path}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Convert forward slashes to backslashes on Win32
|
101
|
+
path = path.tr("/", @sep) if @win32
|
102
|
+
super(path)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Win32 only
|
106
|
+
#
|
107
|
+
# Removes the decoration from a path string. For example,
|
108
|
+
# C:\Path\File[5].txt would become C:\Path\File.txt.
|
109
|
+
def undecorate
|
110
|
+
unless @win32
|
111
|
+
raise NotImplementedError, "not supported on this platform"
|
112
|
+
end
|
113
|
+
buf = 0.chr * MAX_PATH
|
114
|
+
buf[0..self.length-1] = self
|
115
|
+
@@PathUndecorate.call(buf)
|
116
|
+
Pathname.new(buf.split(0.chr).first)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Removes trailing slash, if present.
|
120
|
+
def pstrip
|
121
|
+
if @win32
|
122
|
+
@@PathRemoveBackslash.call(self)
|
123
|
+
self.strip!
|
124
|
+
else
|
125
|
+
if self[-1] == @sep
|
126
|
+
self.strip!
|
127
|
+
self.chop!
|
128
|
+
end
|
129
|
+
end
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
133
|
+
# Splits a pathname into pieces based on the path separator. For example,
|
134
|
+
# "/foo/bar/baz" would return a three element array of ['foo','bar','baz'].
|
135
|
+
def to_a
|
136
|
+
array = split(@sep) # Split string by path separator
|
137
|
+
array.delete("") # Remove empty elements
|
138
|
+
array
|
139
|
+
end
|
140
|
+
|
141
|
+
# Yields each component of the path name to a block.
|
142
|
+
def each
|
143
|
+
self.to_a.each{ |element| yield element }
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns the root directory of the path, or '.' if there is no root
|
147
|
+
# directory.
|
148
|
+
#
|
149
|
+
# On Unix, this means the '/' character. On Win32 systems, this can
|
150
|
+
# refer to the drive letter, or the server and share path if the path
|
151
|
+
# is a UNC path.
|
152
|
+
def root
|
153
|
+
dir = "."
|
154
|
+
if @win32
|
155
|
+
buf = 0.chr * MAX_PATH
|
156
|
+
buf[0..self.length-1] = self
|
157
|
+
|
158
|
+
if @@PathStripToRoot.call(buf) > 0
|
159
|
+
dir = Pathname.new(buf.split(0.chr).first)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
dir = File.dirname(self)
|
163
|
+
while dir != "/" && dir != "."
|
164
|
+
dir = File.dirname(dir)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
dir = "." if dir.empty?
|
168
|
+
dir
|
169
|
+
end
|
170
|
+
|
171
|
+
# Returns whether or not the path consists only of a root directory.
|
172
|
+
def root?
|
173
|
+
if @win32
|
174
|
+
@@PathIsRoot.call(self) > 0
|
175
|
+
else
|
176
|
+
self == root
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Win32 only
|
181
|
+
#
|
182
|
+
# Determines if the string is a valid Universal Naming Convention (UNC)
|
183
|
+
# for a server and share path.
|
184
|
+
def unc?
|
185
|
+
unless @win32
|
186
|
+
raise NotImplementedError, "not supported on this platform"
|
187
|
+
end
|
188
|
+
|
189
|
+
@@PathIsUNC.call(self) > 0
|
190
|
+
end
|
191
|
+
|
192
|
+
# Win32 only
|
193
|
+
#
|
194
|
+
# Returns the drive number that corresponds to the root, or nil if not
|
195
|
+
# applicable.
|
196
|
+
#
|
197
|
+
# For example, Pathname.new("C:\\foo").drive_number would return 2.
|
198
|
+
def drive_number
|
199
|
+
unless @win32
|
200
|
+
raise NotImplementedError, "not supported on this platform"
|
201
|
+
end
|
202
|
+
|
203
|
+
num = @@PathGetDriveNumber.call(self)
|
204
|
+
num >= 0 ? num : nil
|
205
|
+
end
|
206
|
+
|
207
|
+
# Pathnames may only be compared against other Pathnames, not strings.
|
208
|
+
def <=>(string)
|
209
|
+
return nil unless string.kind_of?(Pathname)
|
210
|
+
super
|
211
|
+
end
|
212
|
+
|
213
|
+
# Adds two Pathname objects together, or a Pathname and a String. It
|
214
|
+
# also automatically cleans the Pathname.
|
215
|
+
#
|
216
|
+
# Example:
|
217
|
+
# path1 = '/foo/bar'
|
218
|
+
# path2 = '../baz'
|
219
|
+
# path1 + path2 # '/foo/baz'
|
220
|
+
#
|
221
|
+
# Adding a root path to an existing path merely replaces the current
|
222
|
+
# path. Adding '.' to an existing path does nothing.
|
223
|
+
def +(string)
|
224
|
+
unless string.kind_of?(Pathname)
|
225
|
+
string = Pathname.new(string)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Any path plus "." is the same directory
|
229
|
+
return self if string == "."
|
230
|
+
|
231
|
+
# Use the builtin PathAppend method if on Windows - much easier
|
232
|
+
if @win32
|
233
|
+
buf = 0.chr * MAX_PATH
|
234
|
+
buf[0..self.length-1] = self
|
235
|
+
@@PathAppend.call(buf, string << 0.chr)
|
236
|
+
buf.strip!
|
237
|
+
return Pathname.new(buf) # PathAppend cleans automatically
|
238
|
+
end
|
239
|
+
|
240
|
+
# If the string is an absolute directory, return it
|
241
|
+
return string if string.absolute?
|
242
|
+
|
243
|
+
array = self.to_a + string.to_a
|
244
|
+
new_string = array.join(@sep)
|
245
|
+
|
246
|
+
unless self.relative? || @win32
|
247
|
+
new_string = @sep + new_string # Add root path back if needed
|
248
|
+
end
|
249
|
+
|
250
|
+
Pathname.new(new_string).clean
|
251
|
+
end
|
252
|
+
|
253
|
+
# Returns whether or not the path is an absolute path.
|
254
|
+
def absolute?
|
255
|
+
!relative?
|
256
|
+
end
|
257
|
+
|
258
|
+
# Returns whether or not the path is a relative path.
|
259
|
+
def relative?
|
260
|
+
if @win32
|
261
|
+
@@PathIsRelative.call(self) > 0
|
262
|
+
else
|
263
|
+
root == "."
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# Removes unnecessary '.' paths and ellides '..' paths appropriately.
|
268
|
+
def clean
|
269
|
+
return self if self.empty?
|
270
|
+
|
271
|
+
if @win32
|
272
|
+
path = 0.chr * MAX_PATH
|
273
|
+
if @@PathCanonicalize.call(path, self) > 0
|
274
|
+
return Pathname.new(path.split(0.chr).first)
|
275
|
+
else
|
276
|
+
return self
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
final = []
|
281
|
+
self.to_a.each{ |element|
|
282
|
+
next if element == "."
|
283
|
+
final.push(element)
|
284
|
+
if element == ".." && self != ".."
|
285
|
+
2.times{ final.pop }
|
286
|
+
end
|
287
|
+
}
|
288
|
+
final = final.join(@sep)
|
289
|
+
final = root + final if root != "."
|
290
|
+
final = "." if final.empty?
|
291
|
+
Pathname.new(final)
|
292
|
+
end
|
293
|
+
alias :cleanpath :clean
|
294
|
+
|
295
|
+
#-- IO methods not handled by facade
|
296
|
+
|
297
|
+
# IO.foreach
|
298
|
+
def foreach(*args, &block)
|
299
|
+
IO.foreach(self, *args, &block)
|
300
|
+
end
|
301
|
+
|
302
|
+
# IO.read
|
303
|
+
def read(*args)
|
304
|
+
IO.read(self, *args)
|
305
|
+
end
|
306
|
+
|
307
|
+
# IO.readlines
|
308
|
+
def readlines(*args)
|
309
|
+
IO.readlines(self, *args)
|
310
|
+
end
|
311
|
+
|
312
|
+
# IO.sysopen
|
313
|
+
def sysopen(*args)
|
314
|
+
IO.sysopen(self, *args)
|
315
|
+
end
|
316
|
+
|
317
|
+
#-- Dir methods not handled by facade
|
318
|
+
|
319
|
+
# Dir.glob
|
320
|
+
def glob(*args)
|
321
|
+
if block_given?
|
322
|
+
Dir.glob(*args){ |file| yield Pathname.new(file) }
|
323
|
+
else
|
324
|
+
Dir.glob(*args).map{ |file| Pathname.new(file) }
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
# Dir.chdir
|
329
|
+
def chdir(&block)
|
330
|
+
Dir.chdir(self, &block)
|
331
|
+
end
|
332
|
+
|
333
|
+
# Dir.entries
|
334
|
+
def entries
|
335
|
+
Dir.entries(self).map{ |file| Pathname.new(file) }
|
336
|
+
end
|
337
|
+
|
338
|
+
# Dir.mkdir
|
339
|
+
def mkdir(*args)
|
340
|
+
Dir.mkdir(self, *args)
|
341
|
+
end
|
342
|
+
|
343
|
+
# Dir.opendir
|
344
|
+
def opendir(&block)
|
345
|
+
Dir.open(self, &block)
|
346
|
+
end
|
347
|
+
|
348
|
+
#-- File methods not handled by facade
|
349
|
+
|
350
|
+
# File.chmod
|
351
|
+
def chmod(mode)
|
352
|
+
File.chmod(mode, self)
|
353
|
+
end
|
354
|
+
|
355
|
+
# File.lchmod
|
356
|
+
def lchmod(mode)
|
357
|
+
File.lchmod(mode, self)
|
358
|
+
end
|
359
|
+
|
360
|
+
# File.chown
|
361
|
+
def chown(owner, group)
|
362
|
+
File.chown(owner, group, self)
|
363
|
+
end
|
364
|
+
|
365
|
+
# File.lchown
|
366
|
+
def lchown(owner, group)
|
367
|
+
File.lchown(owner, group, self)
|
368
|
+
end
|
369
|
+
|
370
|
+
# File.fnmatch
|
371
|
+
def fnmatch(pattern, *args)
|
372
|
+
File.fnmatch(pattern, self, *args)
|
373
|
+
end
|
374
|
+
|
375
|
+
# File.fnmatch?
|
376
|
+
def fnmatch?(pattern, *args)
|
377
|
+
File.fnmatch?(pattern, self, *args)
|
378
|
+
end
|
379
|
+
|
380
|
+
# File.link
|
381
|
+
def link(old)
|
382
|
+
File.link(old, self)
|
383
|
+
end
|
384
|
+
|
385
|
+
# File.open
|
386
|
+
def open(*args, &block)
|
387
|
+
File.open(self, *args, &block)
|
388
|
+
end
|
389
|
+
|
390
|
+
# File.rename
|
391
|
+
def rename(name)
|
392
|
+
File.rename(self, name)
|
393
|
+
end
|
394
|
+
|
395
|
+
# File.symlink
|
396
|
+
def symlink(old)
|
397
|
+
File.symlink(old, self)
|
398
|
+
end
|
399
|
+
|
400
|
+
# File.truncate
|
401
|
+
def truncate(length)
|
402
|
+
File.truncate(self, length)
|
403
|
+
end
|
404
|
+
|
405
|
+
# File.utime
|
406
|
+
def utime(atime, mtime)
|
407
|
+
File.utime(atime, mtime, self)
|
408
|
+
end
|
409
|
+
|
410
|
+
# File.basename
|
411
|
+
def basename(*args)
|
412
|
+
File.basename(self, *args)
|
413
|
+
end
|
414
|
+
|
415
|
+
# File.expand_path
|
416
|
+
def expand_path(*args)
|
417
|
+
File.expand_path(self, *args)
|
418
|
+
end
|
419
|
+
|
420
|
+
#--
|
421
|
+
# ftools facade
|
422
|
+
#++
|
423
|
+
|
424
|
+
# ftools File.copy
|
425
|
+
def copy(*args)
|
426
|
+
File.copy(self, *args)
|
427
|
+
end
|
428
|
+
|
429
|
+
#--
|
430
|
+
# FileUtils facade. Note that methods already covered by File and Dir
|
431
|
+
# are not defined here (pwd, mkdir, etc).
|
432
|
+
#++
|
433
|
+
|
434
|
+
# FileUtils.cd
|
435
|
+
def cd(*args, &block)
|
436
|
+
FileUtils.cd(self, *args, &block)
|
437
|
+
end
|
438
|
+
|
439
|
+
# FileUtils.mkdir_p
|
440
|
+
def mkdir_p(*args)
|
441
|
+
FileUtils.mkdir_p(self, *args)
|
442
|
+
end
|
443
|
+
alias mkpath mkdir_p
|
444
|
+
|
445
|
+
# FileUtils.ln
|
446
|
+
def ln(*args)
|
447
|
+
FileUtils.ln(self, *args)
|
448
|
+
end
|
449
|
+
|
450
|
+
# FileUtils.ln_s
|
451
|
+
def ln_s(*args)
|
452
|
+
FileUtils.ln_s(self, *args)
|
453
|
+
end
|
454
|
+
|
455
|
+
# FileUtils.ln_sf
|
456
|
+
def ln_sf(*args)
|
457
|
+
FileUtils.ln_sf(self, *args)
|
458
|
+
end
|
459
|
+
|
460
|
+
# FileUtils.cp
|
461
|
+
def cp(*args)
|
462
|
+
FileUtils.cp(self, *args)
|
463
|
+
end
|
464
|
+
|
465
|
+
# FileUtils.cp_r
|
466
|
+
def cp_r(*args)
|
467
|
+
FileUtils.cp_r(self, *args)
|
468
|
+
end
|
469
|
+
|
470
|
+
# FileUtils.mv
|
471
|
+
def mv(*args)
|
472
|
+
FileUtils.mv(self, *args)
|
473
|
+
end
|
474
|
+
|
475
|
+
# FileUtils.rm
|
476
|
+
def rm(*args)
|
477
|
+
FileUtils.rm(self, *args)
|
478
|
+
end
|
479
|
+
alias remove rm
|
480
|
+
|
481
|
+
# FileUtils.rm_f
|
482
|
+
def rm_f(*args)
|
483
|
+
FileUtils.rm_f(self, *args)
|
484
|
+
end
|
485
|
+
|
486
|
+
# FileUtils.rm_r
|
487
|
+
def rm_r(*args)
|
488
|
+
FileUtils.rm_r(self, *args)
|
489
|
+
end
|
490
|
+
|
491
|
+
# FileUtils.rm_rf
|
492
|
+
def rm_rf(*args)
|
493
|
+
FileUtils.rm_rf(self, *args)
|
494
|
+
end
|
495
|
+
alias rmtree rm_rf
|
496
|
+
|
497
|
+
# FileUtils.install
|
498
|
+
def install(*args)
|
499
|
+
FileUtils.install(self, *args)
|
500
|
+
end
|
501
|
+
|
502
|
+
# FileUtils.touch
|
503
|
+
def touch(*args)
|
504
|
+
FileUtils.touch(*args)
|
505
|
+
end
|
506
|
+
|
507
|
+
# FileUtils.compare_file
|
508
|
+
def compare_file(file)
|
509
|
+
FileUtils.compare_file(self, file)
|
510
|
+
end
|
511
|
+
|
512
|
+
# FileUtils.uptodate?
|
513
|
+
def uptodate?(*args)
|
514
|
+
FileUtils.uptodate(self, *args)
|
515
|
+
end
|
516
|
+
|
517
|
+
# FileUtils.copy_file
|
518
|
+
def copy_file(*args)
|
519
|
+
FileUtils.copy_file(self, *args)
|
520
|
+
end
|
521
|
+
|
522
|
+
# FileUtils.remove_dir
|
523
|
+
def remove_dir(*args)
|
524
|
+
FileUtils.remove_dir(self, *args)
|
525
|
+
end
|
526
|
+
|
527
|
+
# FileUtils.remove_file
|
528
|
+
def remove_file(*args)
|
529
|
+
FileUtils.remove_dir(self, *args)
|
530
|
+
end
|
531
|
+
|
532
|
+
# FileUtils.copy_entry
|
533
|
+
def copy_entry(*args)
|
534
|
+
FileUtils.copy_entry(self, *args)
|
535
|
+
end
|
536
|
+
end
|
data/test/tc_pathname.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
##############################################
|
2
|
+
# tc_pathname.rb
|
3
|
+
#
|
4
|
+
# Test suite for the pathname package (Unix)
|
5
|
+
##############################################
|
6
|
+
Dir.chdir ".." if File.basename(Dir.pwd) == "test"
|
7
|
+
$LOAD_PATH.unshift Dir.pwd
|
8
|
+
$LOAD_PATH.unshift Dir.pwd + "/lib"
|
9
|
+
|
10
|
+
require "pathname2"
|
11
|
+
require "test/unit"
|
12
|
+
|
13
|
+
class TC_Pathname < Test::Unit::TestCase
|
14
|
+
def setup
|
15
|
+
@path = Pathname.new("/usr/local/bin")
|
16
|
+
end
|
17
|
+
|
18
|
+
# Convenience method for test_plus
|
19
|
+
def assert_pathname_plus(a, b, c)
|
20
|
+
a = Pathname.new(a)
|
21
|
+
b = Pathname.new(b)
|
22
|
+
c = Pathname.new(c)
|
23
|
+
assert_equal(a, b + c)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Convenience method for test_spaceship operator
|
27
|
+
def assert_pathname_cmp(int, s1, s2)
|
28
|
+
p1 = Pathname.new(s1)
|
29
|
+
p2 = Pathname.new(s2)
|
30
|
+
result = p1 <=> p2
|
31
|
+
assert_equal(int, result)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_version
|
35
|
+
assert_equal("1.0.0", Pathname::VERSION)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_unc
|
39
|
+
assert_raises(NotImplementedError){ @path.unc? }
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_enumerable
|
43
|
+
assert_respond_to(@path, :each)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_root
|
47
|
+
assert_respond_to(@path, :root)
|
48
|
+
assert_nothing_raised{ @path.root }
|
49
|
+
assert_equal("/", @path.root)
|
50
|
+
|
51
|
+
path1 = Pathname.new("foo")
|
52
|
+
path2 = Pathname.new("foo/bar/baz")
|
53
|
+
assert_equal(".", path1.root)
|
54
|
+
assert_equal(".", path2.root)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_root?
|
58
|
+
assert_respond_to(@path, :root?)
|
59
|
+
assert_nothing_raised{ @path.root? }
|
60
|
+
|
61
|
+
path1 = Pathname.new("/")
|
62
|
+
path2 = Pathname.new("a")
|
63
|
+
assert_equal(true, path1.root?)
|
64
|
+
assert_equal(false, path2.root?)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_absolute
|
68
|
+
assert_respond_to(@path, :absolute?)
|
69
|
+
assert_nothing_raised{ @path.absolute? }
|
70
|
+
assert_equal(true, Pathname.new("/usr/bin/ruby").absolute?)
|
71
|
+
assert_equal(false, Pathname.new("foo").absolute?)
|
72
|
+
assert_equal(false, Pathname.new("foo/bar").absolute?)
|
73
|
+
assert_equal(false, Pathname.new("../foo/bar").absolute?)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_relative
|
77
|
+
assert_respond_to(@path, :relative?)
|
78
|
+
assert_nothing_raised{ @path.relative? }
|
79
|
+
assert_equal(false, Pathname.new("/usr/bin/ruby").relative?)
|
80
|
+
assert_equal(true, Pathname.new("foo").relative?)
|
81
|
+
assert_equal(true, Pathname.new("foo/bar").relative?)
|
82
|
+
assert_equal(true, Pathname.new("../foo/bar").relative?)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_to_a
|
86
|
+
assert_respond_to(@path, :to_a)
|
87
|
+
assert_nothing_raised{ @path.to_a }
|
88
|
+
assert_kind_of(Array, @path.to_a)
|
89
|
+
assert_equal(%w/usr local bin/, @path.to_a)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_spaceship_operator
|
93
|
+
assert_respond_to(@path, :<=>)
|
94
|
+
|
95
|
+
assert_pathname_cmp( 0, "/foo/bar", "/foo/bar")
|
96
|
+
assert_pathname_cmp(-1, "/foo/bar", "/foo/zap")
|
97
|
+
assert_pathname_cmp( 1, "/foo/zap", "/foo/bar")
|
98
|
+
assert_pathname_cmp(-1, "foo", "foo/")
|
99
|
+
assert_pathname_cmp(-1, "foo/", "foo/bar")
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_plus_operator
|
103
|
+
assert_respond_to(@path, :+)
|
104
|
+
|
105
|
+
# Standard stuff
|
106
|
+
assert_pathname_plus("/foo/bar", "/foo", "bar")
|
107
|
+
assert_pathname_plus("foo/bar", "foo", "bar")
|
108
|
+
assert_pathname_plus("foo", "foo", ".")
|
109
|
+
assert_pathname_plus("foo", ".", "foo")
|
110
|
+
assert_pathname_plus("/foo", "bar", "/foo")
|
111
|
+
assert_pathname_plus("foo", "foo/bar", "..")
|
112
|
+
assert_pathname_plus("/foo", "/", "../foo")
|
113
|
+
assert_pathname_plus("foo/zap", "foo/bar", "../zap")
|
114
|
+
assert_pathname_plus(".", "foo", "..")
|
115
|
+
assert_pathname_plus("foo", "..", "foo") # Auto clean
|
116
|
+
assert_pathname_plus("foo", "..", "../foo") # Auto clean
|
117
|
+
|
118
|
+
# Edge cases
|
119
|
+
assert_pathname_plus(".", ".", ".")
|
120
|
+
assert_pathname_plus("/", "/", "..")
|
121
|
+
assert_pathname_plus(".", "..", "..")
|
122
|
+
assert_pathname_plus(".", "foo", "..")
|
123
|
+
end
|
124
|
+
|
125
|
+
# Any tests marked with "***" mean that this behavior is different than
|
126
|
+
# the current implementation. It also means I disagree with the current
|
127
|
+
# implementation.
|
128
|
+
def test_cleanpath
|
129
|
+
# Standard stuff
|
130
|
+
assert_equal("/a/b/c", Pathname.new("/a/b/c").cleanpath)
|
131
|
+
assert_equal("b/c", Pathname.new("./b/c").cleanpath)
|
132
|
+
assert_equal("a", Pathname.new("a/.").cleanpath) # ***
|
133
|
+
assert_equal("a/c", Pathname.new("a/./c").cleanpath)
|
134
|
+
assert_equal("a/b", Pathname.new("a/b/.").cleanpath) # ***
|
135
|
+
assert_equal(".", Pathname.new("a/../.").cleanpath) # ***
|
136
|
+
assert_equal("/a", Pathname.new("/a/b/..").cleanpath)
|
137
|
+
assert_equal("/b", Pathname.new("/a/../b").cleanpath)
|
138
|
+
assert_equal("d", Pathname.new("a/../../d").cleanpath) # ***
|
139
|
+
|
140
|
+
# Edge cases
|
141
|
+
assert_equal("", Pathname.new("").cleanpath)
|
142
|
+
assert_equal(".", Pathname.new(".").cleanpath)
|
143
|
+
assert_equal("..", Pathname.new("..").cleanpath)
|
144
|
+
assert_equal('/', Pathname.new('/').cleanpath)
|
145
|
+
assert_equal('/', Pathname.new('//').cleanpath)
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_facade_io
|
149
|
+
assert_respond_to(@path, :foreach)
|
150
|
+
assert_respond_to(@path, :read)
|
151
|
+
assert_respond_to(@path, :readlines)
|
152
|
+
assert_respond_to(@path, :sysopen)
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_facade_file
|
156
|
+
File.methods(false).each{ |method|
|
157
|
+
assert_respond_to(@path, method.to_sym)
|
158
|
+
}
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_facade_dir
|
162
|
+
Dir.methods(false).each{ |method|
|
163
|
+
assert_respond_to(@path, method.to_sym)
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_facade_fileutils
|
168
|
+
methods = FileUtils.public_instance_methods
|
169
|
+
methods -= File.methods(false)
|
170
|
+
methods -= Dir.methods(false)
|
171
|
+
methods.delete_if{ |m| m =~ /stream/ }
|
172
|
+
methods.delete("identical?")
|
173
|
+
|
174
|
+
methods.each{ |method|
|
175
|
+
assert_respond_to(@path, method.to_sym)
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
def teardown
|
180
|
+
@path = nil
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
############################################
|
2
|
+
# tc_pathname.rb
|
3
|
+
#
|
4
|
+
# Test suite for the pathname package.
|
5
|
+
############################################
|
6
|
+
Dir.chdir ".." if File.basename(Dir.pwd) == "test"
|
7
|
+
$LOAD_PATH.unshift Dir.pwd
|
8
|
+
$LOAD_PATH.unshift Dir.pwd + "/lib"
|
9
|
+
|
10
|
+
require "pathname2"
|
11
|
+
require "test/unit"
|
12
|
+
|
13
|
+
class TC_Pathname < Test::Unit::TestCase
|
14
|
+
def setup
|
15
|
+
@fpath = Pathname.new("C:/Program Files/Windows NT/Accessories")
|
16
|
+
@bpath = Pathname.new("C:\\Program Files\\Windows NT\\Accessories")
|
17
|
+
@upath = Pathname.new("\\\\foo\\bar\\baz")
|
18
|
+
@npath = Pathname.new("foo\\bar\\baz")
|
19
|
+
@rpath = Pathname.new("Z:\\")
|
20
|
+
@xpath = Pathname.new("\\\\foo\\bar")
|
21
|
+
@ypath = Pathname.new("\\\\foo")
|
22
|
+
@zpath = Pathname.new("\\\\")
|
23
|
+
@epath = Pathname.new("")
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_version
|
27
|
+
assert_equal("1.0.0", Pathname::VERSION)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Convenience method for test_plus
|
31
|
+
def assert_pathname_plus(a, b, c)
|
32
|
+
a = Pathname.new(a)
|
33
|
+
b = Pathname.new(b)
|
34
|
+
c = Pathname.new(c)
|
35
|
+
assert_equal(a, b + c)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Convenience method for test_spaceship operator
|
39
|
+
def assert_pathname_cmp(int, s1, s2)
|
40
|
+
p1 = Pathname.new(s1)
|
41
|
+
p2 = Pathname.new(s2)
|
42
|
+
result = p1 <=> p2
|
43
|
+
assert_equal(int, result)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_each
|
47
|
+
assert_respond_to(@fpath, :each)
|
48
|
+
assert_nothing_raised{ @fpath.each{ |e| } }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Fails due to PathIsURL for some reason
|
52
|
+
#def test_immutability
|
53
|
+
# path = "C:\\Program Files\\foo\\bar".freeze
|
54
|
+
# assert_equal(true, path.frozen?)
|
55
|
+
# assert_nothing_raised{ Pathname.new(path) }
|
56
|
+
# assert_nothing_raised{ Pathname.new(path).root }
|
57
|
+
#end
|
58
|
+
|
59
|
+
def test_plus_operator
|
60
|
+
# Standard stuff
|
61
|
+
assert_pathname_plus("C:\\a\\b", "C:\\a", "b")
|
62
|
+
assert_pathname_plus("C:\\b", "a", "C:\\b")
|
63
|
+
assert_pathname_plus("a\\b", "a", "b")
|
64
|
+
assert_pathname_plus("C:\\b", "C:\\a", "..\\b")
|
65
|
+
assert_pathname_plus("C:\\a\\b", "C:\\a\\.", "\\b")
|
66
|
+
assert_pathname_plus("C:\\a\\b.txt", "C:\\a", "b.txt")
|
67
|
+
|
68
|
+
# UNC paths
|
69
|
+
assert_pathname_plus("\\\\foo\\bar", "\\\\foo", "bar")
|
70
|
+
assert_pathname_plus("\\\\foo", "\\\\", "foo")
|
71
|
+
assert_pathname_plus("\\\\", "\\\\", "")
|
72
|
+
assert_pathname_plus("\\\\foo\\baz", "\\\\foo\\bar", "\\..\\baz")
|
73
|
+
assert_pathname_plus("\\\\", "\\\\", "..\\..\\..\\..")
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_clean
|
77
|
+
# Our preset stuff
|
78
|
+
assert_equal("C:\\Program Files\\Windows NT\\Accessories", @fpath.clean)
|
79
|
+
assert_equal("C:\\Program Files\\Windows NT\\Accessories", @bpath.clean)
|
80
|
+
assert_equal("\\\\foo\\bar\\baz", @upath.clean)
|
81
|
+
assert_equal("foo\\bar\\baz", @npath.clean)
|
82
|
+
assert_equal("Z:\\", @rpath.clean)
|
83
|
+
assert_equal("\\\\foo\\bar", @xpath.clean)
|
84
|
+
assert_equal("\\\\foo", @ypath.clean)
|
85
|
+
assert_equal("\\\\", @zpath.clean)
|
86
|
+
assert_equal("", @epath.clean)
|
87
|
+
|
88
|
+
# Standard stuff
|
89
|
+
assert_equal("C:\\a\\c", Pathname.new("C:\\a\\.\\b\\..\\c").clean)
|
90
|
+
assert_equal("C:\\a", Pathname.new("C:\\.\\a").clean)
|
91
|
+
assert_equal("C:\\a\\b", Pathname.new("C:\\a\\.\\b").clean)
|
92
|
+
assert_equal("C:\\b", Pathname.new("C:\\a\\..\\b").clean)
|
93
|
+
assert_equal("C:\\a", Pathname.new("C:\\a\\.").clean)
|
94
|
+
assert_equal("C:\\d", Pathname.new("C:\\..\\..\\..\\d").clean)
|
95
|
+
assert_equal("C:\\a\\", Pathname.new("C:\\a\\").clean)
|
96
|
+
|
97
|
+
# Edge cases
|
98
|
+
assert_equal("\\", Pathname.new(".").clean)
|
99
|
+
assert_equal("\\", Pathname.new("..").clean)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_absolute
|
103
|
+
assert_equal(true, @fpath.absolute?)
|
104
|
+
assert_equal(true, @bpath.absolute?)
|
105
|
+
assert_equal(true, @upath.absolute?)
|
106
|
+
assert_equal(false, @npath.absolute?)
|
107
|
+
assert_equal(true, @rpath.absolute?)
|
108
|
+
assert_equal(true, @xpath.absolute?)
|
109
|
+
assert_equal(true, @ypath.absolute?)
|
110
|
+
assert_equal(true, @zpath.absolute?)
|
111
|
+
assert_equal(false, @epath.absolute?)
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_relative
|
115
|
+
assert_equal(false, @fpath.relative?)
|
116
|
+
assert_equal(false, @bpath.relative?)
|
117
|
+
assert_equal(false, @upath.relative?)
|
118
|
+
assert_equal(true, @npath.relative?)
|
119
|
+
assert_equal(false, @rpath.relative?)
|
120
|
+
assert_equal(false, @xpath.relative?)
|
121
|
+
assert_equal(false, @ypath.relative?)
|
122
|
+
assert_equal(false, @zpath.relative?)
|
123
|
+
assert_equal(true, @epath.relative?)
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_root
|
127
|
+
assert_equal("C:\\", @fpath.root)
|
128
|
+
assert_equal("C:\\", @bpath.root)
|
129
|
+
assert_equal("\\\\foo\\bar", @upath.root)
|
130
|
+
assert_equal(".", @npath.root)
|
131
|
+
assert_equal("Z:\\", @rpath.root)
|
132
|
+
assert_equal("\\\\foo\\bar", @xpath.root)
|
133
|
+
assert_equal("\\\\foo", @ypath.root)
|
134
|
+
assert_equal("\\\\", @zpath.root)
|
135
|
+
assert_equal(".", @epath.root)
|
136
|
+
|
137
|
+
# Edge cases
|
138
|
+
assert_equal(".", Pathname.new("..").root)
|
139
|
+
assert_equal(".", Pathname.new(".").root)
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_drive_number
|
143
|
+
assert_equal(2, @fpath.drive_number)
|
144
|
+
assert_equal(2, @bpath.drive_number)
|
145
|
+
assert_equal(nil, @upath.drive_number)
|
146
|
+
assert_equal(nil, @npath.drive_number)
|
147
|
+
assert_equal(25, @rpath.drive_number)
|
148
|
+
assert_equal(nil, @xpath.drive_number)
|
149
|
+
assert_equal(nil, @ypath.drive_number)
|
150
|
+
assert_equal(nil, @zpath.drive_number)
|
151
|
+
assert_equal(nil, @epath.drive_number)
|
152
|
+
|
153
|
+
# Edge cases
|
154
|
+
assert_equal(nil, Pathname.new("..").drive_number)
|
155
|
+
assert_equal(nil, Pathname.new(".").drive_number)
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_to_a
|
159
|
+
expected = ["C:", "Program Files", "Windows NT", "Accessories"]
|
160
|
+
assert_equal(expected, @fpath.to_a)
|
161
|
+
assert_equal(expected, @bpath.to_a)
|
162
|
+
assert_equal(["foo","bar","baz"], @upath.to_a)
|
163
|
+
assert_equal(["foo","bar","baz"], @npath.to_a)
|
164
|
+
assert_equal(["Z:"], @rpath.to_a)
|
165
|
+
assert_equal(["foo","bar"], @xpath.to_a)
|
166
|
+
assert_equal(["foo"], @ypath.to_a)
|
167
|
+
assert_equal([], @zpath.to_a)
|
168
|
+
assert_equal([], @epath.to_a)
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_is_root
|
172
|
+
assert_equal(false, @fpath.root?)
|
173
|
+
assert_equal(false, @bpath.root?)
|
174
|
+
assert_equal(false, @upath.root?)
|
175
|
+
assert_equal(false, @npath.root?)
|
176
|
+
assert_equal(true, @rpath.root?)
|
177
|
+
assert_equal(true, @xpath.root?)
|
178
|
+
assert_equal(true, @ypath.root?)
|
179
|
+
assert_equal(true, @zpath.root?)
|
180
|
+
assert_equal(false, @epath.root?)
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_facade_io
|
184
|
+
assert_respond_to(@fpath, :foreach)
|
185
|
+
assert_respond_to(@fpath, :read)
|
186
|
+
assert_respond_to(@fpath, :readlines)
|
187
|
+
assert_respond_to(@fpath, :sysopen)
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_facade_file
|
191
|
+
File.methods(false).each{ |method|
|
192
|
+
assert_respond_to(@fpath, method.to_sym)
|
193
|
+
}
|
194
|
+
assert_respond_to(@fpath, :catname) # ftools check
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_facade_dir
|
198
|
+
Dir.methods(false).each{ |method|
|
199
|
+
assert_respond_to(@fpath, method.to_sym)
|
200
|
+
}
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_facade_fileutils
|
204
|
+
methods = FileUtils.public_instance_methods
|
205
|
+
methods -= File.methods(false)
|
206
|
+
methods -= Dir.methods(false)
|
207
|
+
methods.delete_if{ |m| m =~ /stream/ }
|
208
|
+
methods.delete_if{ |m| m =~ /^ln/ }
|
209
|
+
methods.delete("identical?")
|
210
|
+
|
211
|
+
methods.each{ |method|
|
212
|
+
assert_respond_to(@fpath, method.to_sym)
|
213
|
+
}
|
214
|
+
end
|
215
|
+
|
216
|
+
def teardown
|
217
|
+
@fpath = nil
|
218
|
+
@bpath = nil
|
219
|
+
@upath = nil
|
220
|
+
@npath = nil
|
221
|
+
@rpath = nil
|
222
|
+
@xpath = nil
|
223
|
+
@ypath = nil
|
224
|
+
@zpath = nil
|
225
|
+
@epath = nil
|
226
|
+
end
|
227
|
+
end
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.10
|
3
|
+
specification_version: 1
|
4
|
+
name: pathname2
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2005-06-11
|
8
|
+
summary: An alternate implementation of the Pathname class
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: djberg96@gmail.com
|
12
|
+
homepage: http://www.rubyforge.org/projects/shards
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
authors:
|
28
|
+
- Daniel J. Berger
|
29
|
+
files:
|
30
|
+
- lib/pathname2.rb
|
31
|
+
- README
|
32
|
+
- CHANGES
|
33
|
+
- MANIFEST
|
34
|
+
- test/tc_pathname_win.rb
|
35
|
+
- test/tc_pathname.rb
|
36
|
+
test_files:
|
37
|
+
- test/tc_pathname.rb
|
38
|
+
rdoc_options: []
|
39
|
+
extra_rdoc_files:
|
40
|
+
- README
|
41
|
+
- CHANGES
|
42
|
+
executables: []
|
43
|
+
extensions: []
|
44
|
+
requirements: []
|
45
|
+
dependencies:
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: facade
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
50
|
+
requirements:
|
51
|
+
-
|
52
|
+
- ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.0
|
55
|
+
version:
|