pathname2 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,2 @@
1
+ == 1.0.0 - 11-Jun-2005
2
+ * Initial release
data/MANIFEST ADDED
@@ -0,0 +1,10 @@
1
+ CHANGES
2
+ MANIFEST
3
+ README
4
+ install.rb
5
+ pathname2.gempsec
6
+
7
+ lib/pathname2.rb
8
+
9
+ test/tc_pathname.rb
10
+ test/tc_pathname_win.rb
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
@@ -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: