pathname2 1.0.0

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 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: