pathname2 1.4.4 → 1.5.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 CHANGED
@@ -1,3 +1,10 @@
1
+ == 1.5.0 - 17-Apr-2006
2
+ * Better subclass handling, in that some methods that previously returned
3
+ hardcoded Pathname.new now return self.class.new.
4
+ * File URL's are now handled on Unix as well (using the 'uri' package).
5
+ * Some comment changes/clarifications.
6
+ * Added the PathnameError class to the pure Ruby version.
7
+
1
8
  == 1.4.4 - 23-Mar-2006
2
9
  * If the path is a symbolic link the Pathname#realpath method
3
10
  now returns the absolute path of that link, i.e. the result
data/README CHANGED
@@ -67,6 +67,8 @@
67
67
  * Pathname#clean works slightly differently. In the old version,
68
68
  Pathname#clean("../a") returns "../a". In this version, it returns "a".
69
69
  This affects other methods, such as Pathname#relative_path_from.
70
+ * Accepts file urls and converts them to paths automatically, e.g.
71
+ file:///foo%20bar/baz becomes '/foo bar/baz'.
70
72
 
71
73
  == Method Priority
72
74
  Because there is some overlap in method names between File, Dir, ftools
data/lib/pathname2.rb CHANGED
@@ -41,6 +41,8 @@ require "facade"
41
41
  require "ftools"
42
42
  require "fileutils"
43
43
 
44
+ class PathnameError < StandardError; end
45
+
44
46
  class Pathname < String
45
47
  extend Facade
46
48
  facade File
@@ -77,12 +79,19 @@ class Pathname < String
77
79
  Win32API.new('shlwapi', 'PathRemoveBackslash', 'P', 'P')
78
80
  end
79
81
 
80
- VERSION = '1.4.4'
82
+ VERSION = '1.5.0'
81
83
  MAX_PATH = 260
82
84
 
83
85
  # Creates and returns a new Pathname object.
84
86
  #
85
- # On Windows systems, all forward slashes are replaced with backslashes.
87
+ # On platforms that define File::ALT_SEPARATOR, all forward slashes are
88
+ # replaced with the value of File::ALT_SEPARATOR. On MS Windows, for
89
+ # example, all forward slashes are replaced with backslashes.
90
+ #
91
+ # File URL's will be converted to Pathname objects, e.g. the file URL
92
+ # "file:///C:/Documents%20and%20Settings" will become
93
+ # 'C:\Documents and Settings'.
94
+ #
86
95
  def initialize(path)
87
96
  if path.length > MAX_PATH
88
97
  msg = "string too long. maximum string length is " + MAX_PATH.to_s
@@ -92,7 +101,9 @@ class Pathname < String
92
101
  @sep = File::ALT_SEPARATOR || File::SEPARATOR
93
102
  @win = RUBY_PLATFORM.match('mswin')
94
103
 
95
- # Handle File URL's for Windows
104
+ # Handle File URL's. The separate methods for Windows are necessary
105
+ # because Ruby's URI class does not (currently) parse absolute file URL's
106
+ # properly when they include a drive letter.
96
107
  if @win
97
108
  if @@PathIsURL.call(path) > 0
98
109
  buf = 0.chr * MAX_PATH
@@ -103,6 +114,11 @@ class Pathname < String
103
114
  raise PathnameError, "invalid file url: #{path}"
104
115
  end
105
116
  end
117
+ else
118
+ if path.index('file:///', 0)
119
+ require 'uri'
120
+ path = URI.decode(URI.parse(path).path)
121
+ end
106
122
  end
107
123
 
108
124
  # Convert forward slashes to backslashes on Windows
@@ -114,11 +130,12 @@ class Pathname < String
114
130
  #
115
131
  # Unlike most Pathname methods, this one assumes that the path actually
116
132
  # exists on your filesystem. If it doesn't, an error is raised.
133
+ #
117
134
  def realpath
118
- pwd = Pathname.new(Dir.pwd)
135
+ pwd = self.class.new(Dir.pwd)
119
136
  File.stat(self) # Check to ensure that the path exists
120
137
  if File.symlink?(self)
121
- Pathname.new(File.readlink(self))
138
+ self.class.new(File.readlink(self))
122
139
  else
123
140
  pwd + self
124
141
  end
@@ -138,9 +155,9 @@ class Pathname < String
138
155
  Dir.foreach(self) { |file|
139
156
  next if file == '.' || file == '..'
140
157
  if with_directory
141
- result << Pathname.new(File.join(self, file))
158
+ result << self.class.new(File.join(self, file))
142
159
  else
143
- result << Pathname.new(file)
160
+ result << self.class.new(file)
144
161
  end
145
162
  }
146
163
  result
@@ -150,6 +167,7 @@ class Pathname < String
150
167
  #
151
168
  # Removes the decoration from a path string. For example,
152
169
  # C:\Path\File[5].txt would become C:\Path\File.txt. Non-destructive.
170
+ #
153
171
  def undecorate
154
172
  unless @win
155
173
  raise NotImplementedError, "not supported on this platform"
@@ -157,12 +175,13 @@ class Pathname < String
157
175
  buf = 0.chr * MAX_PATH
158
176
  buf[0..self.length-1] = self
159
177
  @@PathUndecorate.call(buf)
160
- Pathname.new(buf.split(0.chr).first)
178
+ self.class.new(buf.split(0.chr).first)
161
179
  end
162
180
 
163
181
  # Windows only
164
182
  #
165
183
  # Performs the substitution of Pathname#undecorate in place.
184
+ #
166
185
  def undecorate!
167
186
  unless @win
168
187
  raise NotImplementedError, "not supported on this platform"
@@ -178,6 +197,7 @@ class Pathname < String
178
197
  #
179
198
  # Returns the short path for a long path name. For example,
180
199
  # C:\Program Files\Java would return C:\Progra~1\Java.
200
+ #
181
201
  def short_path
182
202
  unless @win
183
203
  raise NotImplementedError, "not supported on this platform"
@@ -185,13 +205,14 @@ class Pathname < String
185
205
  buf = 0.chr * MAX_PATH
186
206
  buf[0..self.length-1] = self
187
207
  @@GetShortPathName.call(self, buf, buf.length)
188
- Pathname.new(buf.split(0.chr).first)
208
+ self.class.new(buf.split(0.chr).first)
189
209
  end
190
210
 
191
211
  # Windows only
192
212
  #
193
213
  # Returns the long path for a long path name. For example,
194
214
  # C:\Progra~1\Java would return C:\Program Files\Java.
215
+ #
195
216
  def long_path
196
217
  unless @win
197
218
  raise NotImplementedError, "not supported on this platform"
@@ -199,10 +220,11 @@ class Pathname < String
199
220
  buf = 0.chr * MAX_PATH
200
221
  buf[0..self.length-1] = self
201
222
  @@GetLongPathName.call(self, buf, buf.length)
202
- Pathname.new(buf.split(0.chr).first)
223
+ self.class.new(buf.split(0.chr).first)
203
224
  end
204
225
 
205
226
  # Removes trailing slash, if present. Non-destructive.
227
+ #
206
228
  def pstrip
207
229
  str = self.dup
208
230
  if @win
@@ -214,10 +236,11 @@ class Pathname < String
214
236
  str.chop!
215
237
  end
216
238
  end
217
- Pathname.new(str)
239
+ self.class.new(str)
218
240
  end
219
241
 
220
242
  # Removes trailing slash, if present. Destructive.
243
+ #
221
244
  def pstrip!
222
245
  if @win
223
246
  @@PathRemoveBackslash.call(self)
@@ -231,8 +254,9 @@ class Pathname < String
231
254
  self
232
255
  end
233
256
 
234
- # Splits a pathname into pieces based on the path separator. For example,
257
+ # Splits a pathname into strings based on the path separator. For example,
235
258
  # "/foo/bar/baz" would return a three element array of ['foo','bar','baz'].
259
+ #
236
260
  def to_a
237
261
  array = split(@sep) # Split string by path separator
238
262
  array.delete("") # Remove empty elements
@@ -240,6 +264,7 @@ class Pathname < String
240
264
  end
241
265
 
242
266
  # Yields each component of the path name to a block.
267
+ #
243
268
  def each
244
269
  to_a.each{ |element| yield element }
245
270
  end
@@ -250,6 +275,7 @@ class Pathname < String
250
275
  # For example, if the path is "/foo/bar/baz", then "/" would be yielded
251
276
  # on the first iteration, "/foo" on the second, "/foo/bar on the third and
252
277
  # finally "/foo/bar/baz".
278
+ #
253
279
  def descend
254
280
  if root?
255
281
  yield root
@@ -272,7 +298,7 @@ class Pathname < String
272
298
  next if root.to_a.include?(element)
273
299
  end
274
300
  path << element << @sep
275
- yield Pathname.new(path.chop)
301
+ yield self.class.new(path.chop)
276
302
  }
277
303
  end
278
304
 
@@ -282,6 +308,7 @@ class Pathname < String
282
308
  # For example, if the path is "/foo/bar/baz", then "/foo/bar/baz" would
283
309
  # be yielded on the first iteration, "/foo/bar" on the second, "/foo" on
284
310
  # the third, and finally "/".
311
+ #
285
312
  def ascend
286
313
  if root?
287
314
  yield root
@@ -301,7 +328,7 @@ class Pathname < String
301
328
  end
302
329
  end
303
330
 
304
- path = Pathname.new(path)
331
+ path = self.class.new(path)
305
332
  yield path
306
333
 
307
334
  if @win && unc?
@@ -323,6 +350,7 @@ class Pathname < String
323
350
  # On Unix, this means the '/' character. On Windows, this can refer
324
351
  # to the drive letter, or the server and share path if the path is a
325
352
  # UNC path.
353
+ #
326
354
  def root
327
355
  dir = "."
328
356
  if @win
@@ -335,10 +363,11 @@ class Pathname < String
335
363
  else
336
364
  dir = "/" if self =~ /^\//
337
365
  end
338
- Pathname.new(dir)
366
+ self.class.new(dir)
339
367
  end
340
368
 
341
369
  # Returns whether or not the path consists only of a root directory.
370
+ #
342
371
  def root?
343
372
  if @win
344
373
  @@PathIsRoot.call(self) > 0
@@ -351,6 +380,7 @@ class Pathname < String
351
380
  #
352
381
  # Determines if the string is a valid Universal Naming Convention (UNC)
353
382
  # for a server and share path.
383
+ #
354
384
  def unc?
355
385
  unless @win
356
386
  raise NotImplementedError, "not supported on this platform"
@@ -365,6 +395,7 @@ class Pathname < String
365
395
  # applicable.
366
396
  #
367
397
  # For example, Pathname.new("C:\\foo").drive_number would return 2.
398
+ #
368
399
  def drive_number
369
400
  unless @win
370
401
  raise NotImplementedError, "not supported on this platform"
@@ -374,13 +405,16 @@ class Pathname < String
374
405
  num >= 0 ? num : nil
375
406
  end
376
407
 
377
- # Pathnames may only be compared against other Pathnames, not strings.
408
+ # Compares two Pathname objects. Note that Pathnames may only be compared
409
+ # against other Pathnames, not strings. Otherwise nil is returned.
410
+ #
378
411
  def <=>(string)
379
412
  return nil unless string.kind_of?(Pathname)
380
413
  super
381
414
  end
382
415
 
383
416
  # Returns the parent directory of the given path.
417
+ #
384
418
  def parent
385
419
  self + ".."
386
420
  end
@@ -394,14 +428,15 @@ class Pathname < String
394
428
  # files, or you may not get expected results.
395
429
  #
396
430
  # Raises an ArgumentError if it cannot find a relative path.
431
+ #
397
432
  def relative_path_from(base)
398
- base = Pathname.new(base) unless base.kind_of?(Pathname)
433
+ base = self.class.new(base) unless base.kind_of?(Pathname)
399
434
 
400
435
  if self.absolute? != base.absolute?
401
436
  raise ArgumentError, "relative path between absolute and relative path"
402
437
  end
403
438
 
404
- return Pathname.new(".") if self == base
439
+ return self.class.new(".") if self == base
405
440
  return self if base == "."
406
441
 
407
442
  # Because of the way the Windows version handles Pathname#clean, we need
@@ -432,9 +467,9 @@ class Pathname < String
432
467
  rel_path = base_arr + dest_arr
433
468
 
434
469
  if rel_path.empty?
435
- Pathname.new(".")
470
+ self.class.new(".")
436
471
  else
437
- Pathname.new(rel_path.join(@sep))
472
+ self.class.new(rel_path.join(@sep))
438
473
  end
439
474
  end
440
475
 
@@ -448,22 +483,23 @@ class Pathname < String
448
483
  #
449
484
  # Adding a root path to an existing path merely replaces the current
450
485
  # path. Adding '.' to an existing path does nothing.
486
+ #
451
487
  def +(string)
452
488
  unless string.kind_of?(Pathname)
453
- string = Pathname.new(string)
489
+ string = self.class.new(string)
454
490
  end
455
491
 
456
492
  # Any path plus "." is the same directory
457
493
  return self if string == "."
458
494
  return string if self == "."
459
495
 
460
- # Use the builtin PathAppend method if on Windows - much easier
496
+ # Use the builtin PathAppend() function if on Windows - much easier
461
497
  if @win
462
498
  buf = 0.chr * MAX_PATH
463
499
  buf[0..self.length-1] = self
464
500
  @@PathAppend.call(buf, string)
465
501
  buf = buf.split("\0").first
466
- return Pathname.new(buf) # PathAppend cleans automatically
502
+ return self.class.new(buf) # PathAppend cleans automatically
467
503
  end
468
504
 
469
505
  # If the string is an absolute directory, return it
@@ -477,15 +513,17 @@ class Pathname < String
477
513
  new_string.replace(temp)
478
514
  end
479
515
 
480
- Pathname.new(new_string).clean
516
+ self.class.new(new_string).clean
481
517
  end
482
518
 
483
519
  # Returns whether or not the path is an absolute path.
520
+ #
484
521
  def absolute?
485
522
  !relative?
486
523
  end
487
524
 
488
525
  # Returns whether or not the path is a relative path.
526
+ #
489
527
  def relative?
490
528
  if @win
491
529
  @@PathIsRelative.call(self) > 0
@@ -495,13 +533,15 @@ class Pathname < String
495
533
  end
496
534
 
497
535
  # Removes unnecessary '.' paths and ellides '..' paths appropriately.
536
+ # Non-destructive.
537
+ #
498
538
  def clean
499
539
  return self if self.empty?
500
540
 
501
541
  if @win
502
542
  path = 0.chr * MAX_PATH
503
543
  if @@PathCanonicalize.call(path, self) > 0
504
- return Pathname.new(path.split(0.chr).first)
544
+ return self.class.new(path.split(0.chr).first)
505
545
  else
506
546
  return self
507
547
  end
@@ -518,12 +558,13 @@ class Pathname < String
518
558
  final = final.join(@sep)
519
559
  final = root._plus_(final) if root != "."
520
560
  final = "." if final.empty?
521
- Pathname.new(final)
561
+ self.class.new(final)
522
562
  end
523
563
  alias :cleanpath :clean
524
564
 
525
565
  # Removes unnecessary '.' paths and ellides '..' paths appropriately.
526
566
  # Modifies the receiver in place.
567
+ #
527
568
  def clean!
528
569
  return self if self.empty?
529
570
 
@@ -546,7 +587,7 @@ class Pathname < String
546
587
  final = final.join(@sep)
547
588
  final = root + final if root != "."
548
589
  final = "." if final.empty?
549
- replace(Pathname.new(final))
590
+ replace(self.class.new(final))
550
591
  self
551
592
  end
552
593
 
@@ -565,9 +606,9 @@ class Pathname < String
565
606
  def find(&block)
566
607
  require "find"
567
608
  if self == "."
568
- Find.find(self){ |f| yield Pathname.new(f.sub(%r{\A\./}, '')) }
609
+ Find.find(self){ |f| yield self.class.new(f.sub(%r{\A\./}, '')) }
569
610
  else
570
- Find.find(self){ |f| yield Pathname.new(f) }
611
+ Find.find(self){ |f| yield self.class.new(f) }
571
612
  end
572
613
  end
573
614
 
@@ -596,12 +637,17 @@ class Pathname < String
596
637
  #-- Dir methods not handled by facade
597
638
 
598
639
  # Dir.glob
640
+ #
641
+ # :no-doc:
642
+ # This differs from Tanaka's implementation in that it does a temporary
643
+ # chdir to the path in question, then performs the glob.
644
+ #
599
645
  def glob(*args)
600
646
  Dir.chdir(self){
601
647
  if block_given?
602
- Dir.glob(*args){ |file| yield Pathname.new(file) }
648
+ Dir.glob(*args){ |file| yield self.class.new(file) }
603
649
  else
604
- Dir.glob(*args).map{ |file| Pathname.new(file) }
650
+ Dir.glob(*args).map{ |file| self.class.new(file) }
605
651
  end
606
652
  }
607
653
  end
@@ -613,7 +659,7 @@ class Pathname < String
613
659
 
614
660
  # Dir.entries
615
661
  def entries
616
- Dir.entries(self).map{ |file| Pathname.new(file) }
662
+ Dir.entries(self).map{ |file| self.class.new(file) }
617
663
  end
618
664
 
619
665
  # Dir.mkdir
@@ -721,7 +767,7 @@ class Pathname < String
721
767
  def mkdir_p(*args)
722
768
  FileUtils.mkdir_p(self, *args)
723
769
  end
724
- alias mkpath mkdir_p
770
+ alias mkpath mkdir_p
725
771
 
726
772
  # FileUtils.ln
727
773
  def ln(*args)
data/test/tc_pathname.rb CHANGED
@@ -5,42 +5,47 @@
5
5
  # line option, it will test against the C extension. Otherwise, it will run
6
6
  # the tests against the pure Ruby version.
7
7
  ##############################################################################
8
- Dir.chdir ".." if File.basename(Dir.pwd) == "test"
8
+ Dir.chdir '..' if File.basename(Dir.pwd) == 'test'
9
9
 
10
10
  # Test against the C extension if a 'c' is provided as an argument.
11
- if ARGV[0] && ARGV[0].chomp.downcase == "c"
12
- $LOAD_PATH.unshift Dir.pwd + "/ext"
11
+ if ARGV[0] && ARGV[0].chomp.downcase == 'c'
12
+ $LOAD_PATH.unshift Dir.pwd + '/ext'
13
13
  else
14
- $LOAD_PATH.unshift Dir.pwd + "/lib"
14
+ $LOAD_PATH.unshift Dir.pwd + '/lib'
15
15
  end
16
16
 
17
- if PLATFORM.match("mswin")
17
+ if PLATFORM.match('mswin')
18
18
  STDERR.puts("Please run 'tc_pathname_win.rb' instead.")
19
19
  exit
20
20
  end
21
21
 
22
- require "pathname2"
23
- require "test/unit"
22
+ require 'pathname2'
23
+ require 'test/unit'
24
+
25
+ class MyPathname < Pathname; end
24
26
 
25
27
  class TC_Pathname < Test::Unit::TestCase
26
28
  def setup
27
29
  @pwd = Dir.pwd
28
- @abs_path = Pathname.new("/usr/local/bin")
29
- @rel_path = Pathname.new("usr/local/bin")
30
- @trl_path = Pathname.new("/usr/local/bin/")
31
- @mul_path = Pathname.new("/usr/local/lib/local/lib")
32
- @rul_path = Pathname.new("usr/local/lib/local/lib")
30
+ @abs_path = Pathname.new('/usr/local/bin')
31
+ @rel_path = Pathname.new('usr/local/bin')
32
+ @trl_path = Pathname.new('/usr/local/bin/')
33
+ @mul_path = Pathname.new('/usr/local/lib/local/lib')
34
+ @rul_path = Pathname.new('usr/local/lib/local/lib')
35
+ @url_path = Pathname.new('file:///foo%20bar/baz')
33
36
  @cur_path = Pathname.new(Dir.pwd)
34
37
 
35
38
  @abs_array = []
36
39
  @rel_array = []
40
+
41
+ @mypath = MyPathname.new('/usr/local/bin')
37
42
  end
38
43
 
39
44
  # Convenience method to verify that the receiver was not modified
40
45
  # except perhaps slashes
41
46
  def assert_non_destructive
42
- assert_equal("/usr/local/bin", @abs_path)
43
- assert_equal("usr/local/bin", @rel_path)
47
+ assert_equal('/usr/local/bin', @abs_path)
48
+ assert_equal('usr/local/bin', @rel_path)
44
49
  end
45
50
 
46
51
  # Convenience method for test_plus
@@ -72,81 +77,86 @@ class TC_Pathname < Test::Unit::TestCase
72
77
  end
73
78
 
74
79
  def test_version
75
- assert_equal("1.4.4", Pathname::VERSION)
80
+ assert_equal('1.5.0', Pathname::VERSION)
81
+ end
82
+
83
+ def test_file_url_path
84
+ assert_equal('/foo bar/baz', @url_path)
76
85
  end
77
86
 
78
87
  def test_realpath
79
88
  assert_respond_to(@abs_path, :realpath)
80
89
  assert_equal(@pwd, Pathname.new('.').realpath)
81
90
  assert_raises(Errno::ENOENT){ Pathname.new('../bogus').realpath }
91
+
82
92
  end
83
93
 
84
94
  # These tests taken directly from Tanaka's pathname.rb. The one failure
85
95
  # (commented out) is due to the fact that Tanaka's cleanpath method returns
86
- # the cleanpath for "../a" as "../a" (i.e. it does nothing) whereas mine
87
- # converts "../a" into just "a". Which is correct? I vote mine, because
88
- # I don't see how you can get "more relative" from a relative path not
96
+ # the cleanpath for '../a' as '../a' (i.e. it does nothing) whereas mine
97
+ # converts '../a' into just 'a'. Which is correct? I vote mine, because
98
+ # I don't see how you can get 'more relative' from a relative path not
89
99
  # already in the pathname.
90
100
  #
91
101
  def test_relative_path_from
92
- assert_relpath("../a", "a", "b")
93
- assert_relpath("../a", "a", "b/")
94
- assert_relpath("../a", "a/", "b")
95
- assert_relpath("../a", "a/", "b/")
96
- assert_relpath("../a", "/a", "/b")
97
- assert_relpath("../a", "/a", "/b/")
98
- assert_relpath("../a", "/a/", "/b")
99
- assert_relpath("../a", "/a/", "/b/")
100
-
101
- assert_relpath("../b", "a/b", "a/c")
102
- assert_relpath("../a", "../a", "../b")
103
-
104
- assert_relpath("a", "a", ".")
105
- assert_relpath("..", ".", "a")
106
-
107
- assert_relpath(".", ".", ".")
108
- assert_relpath(".", "..", "..")
109
- assert_relpath("..", "..", ".")
110
-
111
- assert_relpath("c/d", "/a/b/c/d", "/a/b")
112
- assert_relpath("../..", "/a/b", "/a/b/c/d")
113
- assert_relpath("../../../../e", "/e", "/a/b/c/d")
114
- assert_relpath("../b/c", "a/b/c", "a/d")
115
-
116
- assert_relpath("../a", "/../a", "/b")
117
- #assert_relpath("../../a", "../a", "b") # fails
118
- assert_relpath(".", "/a/../../b", "/b")
119
- assert_relpath("..", "a/..", "a")
120
- assert_relpath(".", "a/../b", "b")
121
-
122
- assert_relpath("a", "a", "b/..")
123
- assert_relpath("b/c", "b/c", "b/..")
124
-
125
- assert_relpath_err("/", ".")
126
- assert_relpath_err(".", "/")
127
- assert_relpath_err("a", "..")
128
- assert_relpath_err(".", "..")
102
+ assert_relpath('../a', 'a', 'b')
103
+ assert_relpath('../a', 'a', 'b/')
104
+ assert_relpath('../a', 'a/', 'b')
105
+ assert_relpath('../a', 'a/', 'b/')
106
+ assert_relpath('../a', '/a', '/b')
107
+ assert_relpath('../a', '/a', '/b/')
108
+ assert_relpath('../a', '/a/', '/b')
109
+ assert_relpath('../a', '/a/', '/b/')
110
+
111
+ assert_relpath('../b', 'a/b', 'a/c')
112
+ assert_relpath('../a', '../a', '../b')
113
+
114
+ assert_relpath('a', 'a', '.')
115
+ assert_relpath('..', '.', 'a')
116
+
117
+ assert_relpath('.', '.', '.')
118
+ assert_relpath('.', '..', '..')
119
+ assert_relpath('..', '..', '.')
120
+
121
+ assert_relpath('c/d', '/a/b/c/d', '/a/b')
122
+ assert_relpath('../..', '/a/b', '/a/b/c/d')
123
+ assert_relpath('../../../../e', '/e', '/a/b/c/d')
124
+ assert_relpath('../b/c', 'a/b/c', 'a/d')
125
+
126
+ assert_relpath('../a', '/../a', '/b')
127
+ #assert_relpath('../../a', '../a', 'b') # fails
128
+ assert_relpath('.', '/a/../../b', '/b')
129
+ assert_relpath('..', 'a/..', 'a')
130
+ assert_relpath('.', 'a/../b', 'b')
131
+
132
+ assert_relpath('a', 'a', 'b/..')
133
+ assert_relpath('b/c', 'b/c', 'b/..')
134
+
135
+ assert_relpath_err('/', '.')
136
+ assert_relpath_err('.', '/')
137
+ assert_relpath_err('a', '..')
138
+ assert_relpath_err('.', '..')
129
139
  end
130
140
 
131
141
  def test_parent
132
142
  assert_respond_to(@abs_path, :parent)
133
- assert_equal("/usr/local", @abs_path.parent)
134
- assert_equal("usr/local", @rel_path.parent)
135
- assert_equal("/", Pathname.new("/").parent)
143
+ assert_equal('/usr/local', @abs_path.parent)
144
+ assert_equal('usr/local', @rel_path.parent)
145
+ assert_equal('/', Pathname.new('/').parent)
136
146
  end
137
147
 
138
148
  def test_pstrip
139
149
  assert_respond_to(@trl_path, :pstrip)
140
150
  assert_nothing_raised{ @trl_path.pstrip }
141
- assert_equal("/usr/local/bin", @trl_path.pstrip)
142
- assert_equal("/usr/local/bin/", @trl_path)
151
+ assert_equal('/usr/local/bin', @trl_path.pstrip)
152
+ assert_equal('/usr/local/bin/', @trl_path)
143
153
  end
144
154
 
145
155
  def test_pstrip_bang
146
156
  assert_respond_to(@trl_path, :pstrip!)
147
157
  assert_nothing_raised{ @trl_path.pstrip! }
148
- assert_equal("/usr/local/bin", @trl_path.pstrip!)
149
- assert_equal("/usr/local/bin", @trl_path)
158
+ assert_equal('/usr/local/bin', @trl_path.pstrip!)
159
+ assert_equal('/usr/local/bin', @trl_path)
150
160
  end
151
161
 
152
162
  def test_ascend
@@ -156,15 +166,15 @@ class TC_Pathname < Test::Unit::TestCase
156
166
  @abs_path.ascend{ |path| @abs_array.push(path) }
157
167
  @rel_path.ascend{ |path| @rel_array.push(path) }
158
168
 
159
- assert_equal("/usr/local/bin", @abs_array[0])
160
- assert_equal("/usr/local", @abs_array[1])
161
- assert_equal("/usr", @abs_array[2])
162
- assert_equal("/", @abs_array[3])
169
+ assert_equal('/usr/local/bin', @abs_array[0])
170
+ assert_equal('/usr/local', @abs_array[1])
171
+ assert_equal('/usr', @abs_array[2])
172
+ assert_equal('/', @abs_array[3])
163
173
  assert_equal(4, @abs_array.length)
164
174
 
165
- assert_equal("usr/local/bin", @rel_array[0])
166
- assert_equal("usr/local", @rel_array[1])
167
- assert_equal("usr", @rel_array[2])
175
+ assert_equal('usr/local/bin', @rel_array[0])
176
+ assert_equal('usr/local', @rel_array[1])
177
+ assert_equal('usr', @rel_array[2])
168
178
  assert_equal(3, @rel_array.length)
169
179
 
170
180
  assert_non_destructive
@@ -177,15 +187,15 @@ class TC_Pathname < Test::Unit::TestCase
177
187
  @abs_path.descend{ |path| @abs_array.push(path) }
178
188
  @rel_path.descend{ |path| @rel_array.push(path) }
179
189
 
180
- assert_equal("/", @abs_array[0])
181
- assert_equal("/usr", @abs_array[1])
182
- assert_equal("/usr/local", @abs_array[2])
183
- assert_equal("/usr/local/bin", @abs_array[3])
190
+ assert_equal('/', @abs_array[0])
191
+ assert_equal('/usr', @abs_array[1])
192
+ assert_equal('/usr/local', @abs_array[2])
193
+ assert_equal('/usr/local/bin', @abs_array[3])
184
194
  assert_equal(4, @abs_array.length)
185
195
 
186
- assert_equal("usr", @rel_array[0])
187
- assert_equal("usr/local", @rel_array[1])
188
- assert_equal("usr/local/bin", @rel_array[2])
196
+ assert_equal('usr', @rel_array[0])
197
+ assert_equal('usr/local', @rel_array[1])
198
+ assert_equal('usr/local/bin', @rel_array[2])
189
199
  assert_equal(3, @rel_array.length)
190
200
 
191
201
  assert_non_destructive
@@ -198,35 +208,35 @@ class TC_Pathname < Test::Unit::TestCase
198
208
 
199
209
  # Delete Eclipse related files
200
210
  children = @cur_path.children
201
- children.delete_if{ |e| File.basename(e) == "CVS" }
202
- children.delete_if{ |e| File.basename(e) == ".cvsignore" }
203
- children.delete_if{ |e| File.basename(e) == ".project" }
211
+ children.delete_if{ |e| File.basename(e) == 'CVS' }
212
+ children.delete_if{ |e| File.basename(e) == '.cvsignore' }
213
+ children.delete_if{ |e| File.basename(e) == '.project' }
204
214
 
205
215
  assert_equal(
206
216
  [
207
- Dir.pwd + "/CHANGES",
208
- Dir.pwd + "/MANIFEST",
209
- Dir.pwd + "/README",
210
- Dir.pwd + "/examples",
211
- Dir.pwd + "/ext",
212
- Dir.pwd + "/install.rb",
213
- Dir.pwd + "/lib",
214
- Dir.pwd + "/pathname2.gemspec",
215
- Dir.pwd + "/test"
217
+ Dir.pwd + '/CHANGES',
218
+ Dir.pwd + '/MANIFEST',
219
+ Dir.pwd + '/README',
220
+ Dir.pwd + '/examples',
221
+ Dir.pwd + '/ext',
222
+ Dir.pwd + '/install.rb',
223
+ Dir.pwd + '/lib',
224
+ Dir.pwd + '/pathname2.gemspec',
225
+ Dir.pwd + '/test'
216
226
  ],
217
227
  children.sort
218
228
  )
219
229
 
220
230
  # Delete Eclipse related files
221
231
  children = @cur_path.children(false)
222
- children.delete("CVS")
223
- children.delete(".cvsignore")
224
- children.delete(".project")
232
+ children.delete('CVS')
233
+ children.delete('.cvsignore')
234
+ children.delete('.project')
225
235
 
226
236
  assert_equal(
227
237
  [
228
- "CHANGES", "MANIFEST", "README", "examples", "ext",
229
- "install.rb", "lib", "pathname2.gemspec", "test"
238
+ 'CHANGES', 'MANIFEST', 'README', 'examples', 'ext',
239
+ 'install.rb', 'lib', 'pathname2.gemspec', 'test'
230
240
  ],
231
241
  children.sort
232
242
  )
@@ -245,8 +255,8 @@ class TC_Pathname < Test::Unit::TestCase
245
255
  assert_nothing_raised{ @abs_path.root }
246
256
  assert_nothing_raised{ @rel_path.root }
247
257
 
248
- assert_equal("/", @abs_path.root)
249
- assert_equal(".", @rel_path.root)
258
+ assert_equal('/', @abs_path.root)
259
+ assert_equal('.', @rel_path.root)
250
260
 
251
261
  assert_non_destructive
252
262
  end
@@ -256,8 +266,8 @@ class TC_Pathname < Test::Unit::TestCase
256
266
  assert_nothing_raised{ @abs_path.root? }
257
267
  assert_nothing_raised{ @rel_path.root? }
258
268
 
259
- path1 = Pathname.new("/")
260
- path2 = Pathname.new("a")
269
+ path1 = Pathname.new('/')
270
+ path2 = Pathname.new('a')
261
271
  assert_equal(true, path1.root?)
262
272
  assert_equal(false, path2.root?)
263
273
 
@@ -272,10 +282,10 @@ class TC_Pathname < Test::Unit::TestCase
272
282
  assert_equal(true, @abs_path.absolute?)
273
283
  assert_equal(false, @rel_path.absolute?)
274
284
 
275
- assert_equal(true, Pathname.new("/usr/bin/ruby").absolute?)
276
- assert_equal(false, Pathname.new("foo").absolute?)
277
- assert_equal(false, Pathname.new("foo/bar").absolute?)
278
- assert_equal(false, Pathname.new("../foo/bar").absolute?)
285
+ assert_equal(true, Pathname.new('/usr/bin/ruby').absolute?)
286
+ assert_equal(false, Pathname.new('foo').absolute?)
287
+ assert_equal(false, Pathname.new('foo/bar').absolute?)
288
+ assert_equal(false, Pathname.new('../foo/bar').absolute?)
279
289
 
280
290
  assert_non_destructive
281
291
  end
@@ -288,10 +298,10 @@ class TC_Pathname < Test::Unit::TestCase
288
298
  assert_equal(false, @abs_path.relative?)
289
299
  assert_equal(true, @rel_path.relative?)
290
300
 
291
- assert_equal(false, Pathname.new("/usr/bin/ruby").relative?)
292
- assert_equal(true, Pathname.new("foo").relative?)
293
- assert_equal(true, Pathname.new("foo/bar").relative?)
294
- assert_equal(true, Pathname.new("../foo/bar").relative?)
301
+ assert_equal(false, Pathname.new('/usr/bin/ruby').relative?)
302
+ assert_equal(true, Pathname.new('foo').relative?)
303
+ assert_equal(true, Pathname.new('foo/bar').relative?)
304
+ assert_equal(true, Pathname.new('../foo/bar').relative?)
295
305
 
296
306
  assert_non_destructive
297
307
  end
@@ -309,55 +319,55 @@ class TC_Pathname < Test::Unit::TestCase
309
319
  def test_spaceship_operator
310
320
  assert_respond_to(@abs_path, :<=>)
311
321
 
312
- assert_pathname_cmp( 0, "/foo/bar", "/foo/bar")
313
- assert_pathname_cmp(-1, "/foo/bar", "/foo/zap")
314
- assert_pathname_cmp( 1, "/foo/zap", "/foo/bar")
315
- assert_pathname_cmp(-1, "foo", "foo/")
316
- assert_pathname_cmp(-1, "foo/", "foo/bar")
322
+ assert_pathname_cmp( 0, '/foo/bar', '/foo/bar')
323
+ assert_pathname_cmp(-1, '/foo/bar', '/foo/zap')
324
+ assert_pathname_cmp( 1, '/foo/zap', '/foo/bar')
325
+ assert_pathname_cmp(-1, 'foo', 'foo/')
326
+ assert_pathname_cmp(-1, 'foo/', 'foo/bar')
317
327
  end
318
328
 
319
329
  def test_plus_operator
320
330
  assert_respond_to(@abs_path, :+)
321
331
 
322
332
  # Standard stuff
323
- assert_pathname_plus("/foo/bar", "/foo", "bar")
324
- assert_pathname_plus("foo/bar", "foo", "bar")
325
- assert_pathname_plus("foo", "foo", ".")
326
- assert_pathname_plus("foo", ".", "foo")
327
- assert_pathname_plus("/foo", "bar", "/foo")
328
- assert_pathname_plus("foo", "foo/bar", "..")
329
- assert_pathname_plus("/foo", "/", "../foo")
330
- assert_pathname_plus("foo/zap", "foo/bar", "../zap")
331
- assert_pathname_plus(".", "foo", "..")
332
- assert_pathname_plus("foo", "..", "foo") # Auto clean
333
- assert_pathname_plus("foo", "..", "../foo") # Auto clean
333
+ assert_pathname_plus('/foo/bar', '/foo', 'bar')
334
+ assert_pathname_plus('foo/bar', 'foo', 'bar')
335
+ assert_pathname_plus('foo', 'foo', '.')
336
+ assert_pathname_plus('foo', '.', 'foo')
337
+ assert_pathname_plus('/foo', 'bar', '/foo')
338
+ assert_pathname_plus('foo', 'foo/bar', '..')
339
+ assert_pathname_plus('/foo', '/', '../foo')
340
+ assert_pathname_plus('foo/zap', 'foo/bar', '../zap')
341
+ assert_pathname_plus('.', 'foo', '..')
342
+ assert_pathname_plus('foo', '..', 'foo') # Auto clean
343
+ assert_pathname_plus('foo', '..', '../foo') # Auto clean
334
344
 
335
345
  # Edge cases
336
- assert_pathname_plus(".", ".", ".")
337
- assert_pathname_plus("/", "/", "..")
338
- assert_pathname_plus(".", "..", "..")
339
- assert_pathname_plus(".", "foo", "..")
346
+ assert_pathname_plus('.', '.', '.')
347
+ assert_pathname_plus('/', '/', '..')
348
+ assert_pathname_plus('.', '..', '..')
349
+ assert_pathname_plus('.', 'foo', '..')
340
350
  end
341
351
 
342
- # Any tests marked with "***" mean that this behavior is different than
352
+ # Any tests marked with '***' mean that this behavior is different than
343
353
  # the current implementation. It also means I disagree with the current
344
354
  # implementation.
345
355
  def test_clean
346
356
  # Standard stuff
347
- assert_equal("/a/b/c", Pathname.new("/a/b/c").cleanpath)
348
- assert_equal("b/c", Pathname.new("./b/c").cleanpath)
349
- assert_equal("a", Pathname.new("a/.").cleanpath) # ***
350
- assert_equal("a/c", Pathname.new("a/./c").cleanpath)
351
- assert_equal("a/b", Pathname.new("a/b/.").cleanpath) # ***
352
- assert_equal(".", Pathname.new("a/../.").cleanpath) # ***
353
- assert_equal("/a", Pathname.new("/a/b/..").cleanpath)
354
- assert_equal("/b", Pathname.new("/a/../b").cleanpath)
355
- assert_equal("d", Pathname.new("a/../../d").cleanpath) # ***
357
+ assert_equal('/a/b/c', Pathname.new('/a/b/c').cleanpath)
358
+ assert_equal('b/c', Pathname.new('./b/c').cleanpath)
359
+ assert_equal('a', Pathname.new('a/.').cleanpath) # ***
360
+ assert_equal('a/c', Pathname.new('a/./c').cleanpath)
361
+ assert_equal('a/b', Pathname.new('a/b/.').cleanpath) # ***
362
+ assert_equal('.', Pathname.new('a/../.').cleanpath) # ***
363
+ assert_equal('/a', Pathname.new('/a/b/..').cleanpath)
364
+ assert_equal('/b', Pathname.new('/a/../b').cleanpath)
365
+ assert_equal('d', Pathname.new('a/../../d').cleanpath) # ***
356
366
 
357
367
  # Edge cases
358
- assert_equal("", Pathname.new("").cleanpath)
359
- assert_equal(".", Pathname.new(".").cleanpath)
360
- assert_equal("..", Pathname.new("..").cleanpath)
368
+ assert_equal('', Pathname.new('').cleanpath)
369
+ assert_equal('.', Pathname.new('.').cleanpath)
370
+ assert_equal('..', Pathname.new('..').cleanpath)
361
371
  assert_equal('/', Pathname.new('/').cleanpath)
362
372
  assert_equal('/', Pathname.new('//').cleanpath)
363
373
 
@@ -388,28 +398,45 @@ class TC_Pathname < Test::Unit::TestCase
388
398
  methods -= File.methods(false)
389
399
  methods -= Dir.methods(false)
390
400
  methods.delete_if{ |m| m =~ /stream/ }
391
- methods.delete("identical?")
401
+ methods.delete('identical?')
392
402
 
393
403
  methods.each{ |method|
394
404
  assert_respond_to(@abs_path, method.to_sym)
395
405
  }
396
406
  end
397
407
 
398
- # Doesn't work properly in 1.4.0
399
408
  def test_facade_find
400
409
  assert_respond_to(@abs_path, :find)
401
410
  assert_nothing_raised{ @abs_path.find{} }
402
411
 
403
412
  Pathname.new(Dir.pwd).find{ |f|
404
- Find.prune if f.match("CVS")
413
+ Find.prune if f.match('CVS')
405
414
  assert_kind_of(Pathname, f)
406
415
  }
407
416
  end
417
+
418
+ # Ensures that subclasses return the subclass as the class, not a hard
419
+ # coded Pathname.
420
+ def test_subclasses
421
+ assert_kind_of(MyPathname, @mypath)
422
+ assert_kind_of(MyPathname, @mypath + MyPathname.new('foo'))
423
+ assert_kind_of(MyPathname, @mypath.realpath)
424
+ assert_kind_of(MyPathname, @mypath.children.first)
425
+ end
408
426
 
409
427
  def teardown
428
+ @pwd = nil
410
429
  @abs_path = nil
411
430
  @rel_path = nil
431
+ @trl_path = nil
432
+ @mul_path = nil
433
+ @rul_path = nil
412
434
  @cur_path = nil
435
+ @abs_path = nil
436
+ @rel_path = nil
437
+ @cur_path = nil
438
+
439
+ @mypath = nil
413
440
 
414
441
  @abs_array.clear
415
442
  @rel_array.clear
@@ -24,6 +24,8 @@ end
24
24
  require "pathname2"
25
25
  require "test/unit"
26
26
 
27
+ class MyPathname < Pathname; end
28
+
27
29
  class TC_Pathname_MSWin < Test::Unit::TestCase
28
30
 
29
31
  def setup
@@ -42,15 +44,18 @@ class TC_Pathname_MSWin < Test::Unit::TestCase
42
44
  @cpath = Pathname.new("C:\\foo\\..\\bar\\.\\baz")
43
45
  @tpath = Pathname.new("C:\\foo\\bar")
44
46
 
47
+ @url_path = Pathname.new("file:///C:/Documents%20and%20Settings")
45
48
  @cur_path = Pathname.new(Dir.pwd)
46
49
 
50
+ @mypath = MyPathname.new("C:\\Program Files")
51
+
47
52
  @abs_array = []
48
53
  @rel_array = []
49
54
  @unc_array = []
50
55
  end
51
56
 
52
57
  def test_version
53
- assert_equal("1.4.4", Pathname::VERSION)
58
+ assert_equal("1.5.0", Pathname::VERSION)
54
59
  end
55
60
 
56
61
  # Convenience method for test_plus
@@ -80,6 +85,11 @@ class TC_Pathname_MSWin < Test::Unit::TestCase
80
85
  Pathname.new(to).relative_path_from(from)
81
86
  }
82
87
  end
88
+
89
+ def test_file_urls
90
+ assert_equal("C:\\Documents and Settings", @url_path)
91
+ assert_raises(PathnameError){ Pathname.new('http://rubyforge.org') }
92
+ end
83
93
 
84
94
  def test_realpath
85
95
  assert_respond_to(@fpath, :realpath)
@@ -605,6 +615,15 @@ class TC_Pathname_MSWin < Test::Unit::TestCase
605
615
  children
606
616
  )
607
617
  end
618
+
619
+ # Ensures that subclasses return the subclass as the class, not a hard
620
+ # coded Pathname.
621
+ def test_subclasses
622
+ assert_kind_of(MyPathname, @mypath)
623
+ assert_kind_of(MyPathname, @mypath + MyPathname.new('foo'))
624
+ assert_kind_of(MyPathname, @mypath.realpath)
625
+ assert_kind_of(MyPathname, @mypath.children.first)
626
+ end
608
627
 
609
628
  def teardown
610
629
  @fpath = nil
metadata CHANGED
@@ -3,11 +3,11 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: pathname2
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.4.4
7
- date: 2006-03-23 00:00:00 -07:00
6
+ version: 1.5.0
7
+ date: 2006-04-17 00:00:00 -06:00
8
8
  summary: An alternate implementation of the Pathname class
9
9
  require_paths:
10
- - lib
10
+ - lib
11
11
  email: djberg96@gmail.com
12
12
  homepage: http://www.rubyforge.org/projects/shards
13
13
  rubyforge_project:
@@ -18,42 +18,40 @@ bindir: bin
18
18
  has_rdoc: true
19
19
  required_ruby_version: !ruby/object:Gem::Version::Requirement
20
20
  requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
24
25
  version:
25
26
  platform: ruby
26
27
  signing_key:
27
28
  cert_chain:
28
29
  authors:
29
- - Daniel J. Berger
30
+ - Daniel J. Berger
30
31
  files:
31
- - lib/pathname2.rb
32
- - CHANGES
33
- - MANIFEST
34
- - README
35
- - test/tc_pathname.rb
36
- - test/tc_pathname_win.rb
32
+ - lib/pathname2.rb
33
+ - CHANGES
34
+ - MANIFEST
35
+ - README
36
+ - test/tc_pathname.rb
37
+ - test/tc_pathname_win.rb
37
38
  test_files:
38
- - test/tc_pathname.rb
39
+ - test/tc_pathname.rb
39
40
  rdoc_options: []
40
-
41
41
  extra_rdoc_files:
42
- - README
43
- - CHANGES
42
+ - README
43
+ - CHANGES
44
44
  executables: []
45
-
46
45
  extensions: []
47
-
48
46
  requirements: []
49
-
50
47
  dependencies:
51
- - !ruby/object:Gem::Dependency
52
- name: facade
53
- version_requirement:
54
- version_requirements: !ruby/object:Gem::Version::Requirement
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- version: 1.0.0
59
- version:
48
+ - !ruby/object:Gem::Dependency
49
+ name: facade
50
+ version_requirement:
51
+ version_requirements: !ruby/object:Gem::Version::Requirement
52
+ requirements:
53
+ -
54
+ - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 1.0.0
57
+ version: