pathname2 1.4.4 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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: