pathname2 1.5.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +9 -0
- data/README +11 -5
- data/lib/pathname2.rb +50 -50
- data/test/tc_pathname.rb +29 -2
- data/test/tc_pathname_win.rb +14 -4
- metadata +31 -28
data/CHANGES
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 1.5.1 - 28-Aug-2006
|
2
|
+
* Added the Kernel#pn method as a shortcut for Pathname.new.
|
3
|
+
* The Pathname#readlink now properly handles symbolic links. The 'fix'
|
4
|
+
from 1.4.4 did not work.
|
5
|
+
* The C extension uses your system's realpath() function for the
|
6
|
+
Pathname#readlink method if it has one.
|
7
|
+
* Added the '/' alias for '+'. So, p1 / p2 is the same as p1 + p2.
|
8
|
+
* The windows-pr package is now required on MS Windows.
|
9
|
+
|
1
10
|
== 1.5.0 - 17-Apr-2006
|
2
11
|
* Better subclass handling, in that some methods that previously returned
|
3
12
|
hardcoded Pathname.new now return self.class.new.
|
data/README
CHANGED
@@ -3,7 +3,10 @@
|
|
3
3
|
|
4
4
|
== Prerequisites
|
5
5
|
* Ruby 1.8.0 or later
|
6
|
-
* facade 1.0.0 or later (available on the RAA)
|
6
|
+
* facade 1.0.0 or later (available on the RAA and as a gem)
|
7
|
+
* windows-pr 0.5.1 or later (available on the RAA and as a gem)
|
8
|
+
|
9
|
+
The windows-pr package is only required on MS Windows.
|
7
10
|
|
8
11
|
== Installation, pure Ruby
|
9
12
|
=== Manual Installation
|
@@ -31,6 +34,7 @@
|
|
31
34
|
path2 = "../zap"
|
32
35
|
|
33
36
|
path1 + path2 # "/foo/bar/zap"
|
37
|
+
path1 / path2 # "/foo/bar/zap" (same as +)
|
34
38
|
path1.exists? # Does this path exist?
|
35
39
|
path1.dirname # "/foo/bar"
|
36
40
|
path1.to_a # ['foo','bar','baz']
|
@@ -43,7 +47,7 @@
|
|
43
47
|
path1.root # "C:\\"
|
44
48
|
path1.to_a # ['C:','foo','bar','baz']
|
45
49
|
|
46
|
-
==
|
50
|
+
== Windows Notes
|
47
51
|
All forward slashes are converted to backslashes for Pathname objects.
|
48
52
|
|
49
53
|
== Differences between Unix and Windows
|
@@ -52,7 +56,7 @@
|
|
52
56
|
while on Unix "." is returned. I consider this an extreme edge case and
|
53
57
|
will not worry myself with it.
|
54
58
|
|
55
|
-
== Differences between the
|
59
|
+
== Differences between Pathname in the standard library and this version
|
56
60
|
* It is a subclass of String (and thus, mixes in Enumerable).
|
57
61
|
* It has sensical to_a and root instance methods.
|
58
62
|
* It works on Windows and Unix. The current implementation does not work
|
@@ -60,15 +64,17 @@
|
|
60
64
|
paths.
|
61
65
|
* The Pathname#cleanpath method works differently - it always returns
|
62
66
|
a canonical pathname. In addition, there is no special consideration
|
63
|
-
for symlinks (yet).
|
67
|
+
for symlinks (yet), though I'm not sure it warrants it.
|
64
68
|
* The Pathname#+ method auto cleans.
|
65
69
|
* It uses a facade for all File and Dir methods, as well as all ftools
|
66
70
|
methods and most FileUtils methods.
|
67
|
-
* Pathname#clean works slightly differently. In the
|
71
|
+
* Pathname#clean works slightly differently. In the stdlib version,
|
68
72
|
Pathname#clean("../a") returns "../a". In this version, it returns "a".
|
69
73
|
This affects other methods, such as Pathname#relative_path_from.
|
70
74
|
* Accepts file urls and converts them to paths automatically, e.g.
|
71
75
|
file:///foo%20bar/baz becomes '/foo bar/baz'.
|
76
|
+
* Adds a Kernel level +pn+ method as a shortcut.
|
77
|
+
* Allows you to add paths together with the '/' operator.
|
72
78
|
|
73
79
|
== Method Priority
|
74
80
|
Because there is some overlap in method names between File, Dir, ftools
|
data/lib/pathname2.rb
CHANGED
@@ -37,9 +37,9 @@
|
|
37
37
|
# Copyright (c) 2005-2006 Daniel J. Berger.
|
38
38
|
# Licensed under the same terms as Ruby itself.
|
39
39
|
#
|
40
|
-
require
|
41
|
-
require
|
42
|
-
require
|
40
|
+
require 'facade'
|
41
|
+
require 'ftools'
|
42
|
+
require 'fileutils'
|
43
43
|
|
44
44
|
class PathnameError < StandardError; end
|
45
45
|
|
@@ -51,35 +51,13 @@ class Pathname < String
|
|
51
51
|
alias :_plus_ :+ # Used to prevent infinite loops in some cases
|
52
52
|
|
53
53
|
if RUBY_PLATFORM.match('mswin')
|
54
|
-
require '
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@@PathCanonicalize = Win32API.new('shlwapi', 'PathCanonicalize','PP','L')
|
59
|
-
@@PathAppend = Win32API.new('shlwapi', 'PathAppend', 'PP', 'L')
|
60
|
-
@@PathIsRoot = Win32API.new('shlwapi', 'PathIsRoot', 'P', 'L')
|
61
|
-
@@PathIsDirectory = Win32API.new('shlwapi', 'PathIsDirectory', 'P', 'L')
|
62
|
-
@@PathIsRelative = Win32API.new('shlwapi', 'PathIsRelative', 'P', 'L')
|
63
|
-
@@PathFileExists = Win32API.new('shlwapi', 'PathFileExists', 'P', 'L')
|
64
|
-
@@PathUndecorate = Win32API.new('shlwapi', 'PathUndecorate', 'P', 'L')
|
65
|
-
|
66
|
-
@@GetShortPathName =
|
67
|
-
Win32API.new('kernel32', 'GetShortPathName', 'PPL', 'L')
|
68
|
-
|
69
|
-
@@GetLongPathName =
|
70
|
-
Win32API.new('kernel32', 'GetLongPathName', 'PPL', 'L')
|
71
|
-
|
72
|
-
@@PathGetDriveNumber =
|
73
|
-
Win32API.new('shlwapi', 'PathGetDriveNumber', 'P', 'L')
|
74
|
-
|
75
|
-
@@PathCreateFromUrl =
|
76
|
-
Win32API.new('shlwapi', 'PathCreateFromUrl', 'PPPL', 'L')
|
77
|
-
|
78
|
-
@@PathRemoveBackslash =
|
79
|
-
Win32API.new('shlwapi', 'PathRemoveBackslash', 'P', 'P')
|
54
|
+
require 'windows/path'
|
55
|
+
require 'windows/file'
|
56
|
+
include Windows::Path
|
57
|
+
include Windows::File
|
80
58
|
end
|
81
59
|
|
82
|
-
VERSION = '1.5.
|
60
|
+
VERSION = '1.5.1'
|
83
61
|
MAX_PATH = 260
|
84
62
|
|
85
63
|
# Creates and returns a new Pathname object.
|
@@ -105,10 +83,10 @@ class Pathname < String
|
|
105
83
|
# because Ruby's URI class does not (currently) parse absolute file URL's
|
106
84
|
# properly when they include a drive letter.
|
107
85
|
if @win
|
108
|
-
if
|
86
|
+
if PathIsURL(path)
|
109
87
|
buf = 0.chr * MAX_PATH
|
110
88
|
len = [buf.length].pack("l")
|
111
|
-
if
|
89
|
+
if PathCreateFromUrl(path, buf, len, 0)
|
112
90
|
path = buf.strip
|
113
91
|
else
|
114
92
|
raise PathnameError, "invalid file url: #{path}"
|
@@ -132,12 +110,23 @@ class Pathname < String
|
|
132
110
|
# exists on your filesystem. If it doesn't, an error is raised.
|
133
111
|
#
|
134
112
|
def realpath
|
135
|
-
pwd = self.class.new(Dir.pwd)
|
136
113
|
File.stat(self) # Check to ensure that the path exists
|
137
114
|
if File.symlink?(self)
|
138
|
-
self.class.new(File.readlink(self))
|
139
|
-
|
140
|
-
|
115
|
+
path = self.class.new(File.readlink(self))
|
116
|
+
if File.symlink?(path)
|
117
|
+
while File.symlink?(path)
|
118
|
+
if path.relative?
|
119
|
+
path = path + File.dirname(path)
|
120
|
+
else
|
121
|
+
path = self.class.new(File.readlink(path))
|
122
|
+
end
|
123
|
+
end
|
124
|
+
else
|
125
|
+
path = self.class.new(File.dirname(self)) + path
|
126
|
+
end
|
127
|
+
path
|
128
|
+
else
|
129
|
+
self.class.new(Dir.pwd) + self
|
141
130
|
end
|
142
131
|
end
|
143
132
|
|
@@ -174,7 +163,7 @@ class Pathname < String
|
|
174
163
|
end
|
175
164
|
buf = 0.chr * MAX_PATH
|
176
165
|
buf[0..self.length-1] = self
|
177
|
-
|
166
|
+
PathUndecorate(buf)
|
178
167
|
self.class.new(buf.split(0.chr).first)
|
179
168
|
end
|
180
169
|
|
@@ -188,7 +177,7 @@ class Pathname < String
|
|
188
177
|
end
|
189
178
|
buf = 0.chr * MAX_PATH
|
190
179
|
buf[0..self.length-1] = self
|
191
|
-
|
180
|
+
PathUndecorate(buf)
|
192
181
|
replace(buf.split(0.chr).first)
|
193
182
|
self
|
194
183
|
end
|
@@ -204,7 +193,7 @@ class Pathname < String
|
|
204
193
|
end
|
205
194
|
buf = 0.chr * MAX_PATH
|
206
195
|
buf[0..self.length-1] = self
|
207
|
-
|
196
|
+
GetShortPathName(self, buf, buf.length)
|
208
197
|
self.class.new(buf.split(0.chr).first)
|
209
198
|
end
|
210
199
|
|
@@ -219,7 +208,7 @@ class Pathname < String
|
|
219
208
|
end
|
220
209
|
buf = 0.chr * MAX_PATH
|
221
210
|
buf[0..self.length-1] = self
|
222
|
-
|
211
|
+
GetLongPathName(self, buf, buf.length)
|
223
212
|
self.class.new(buf.split(0.chr).first)
|
224
213
|
end
|
225
214
|
|
@@ -228,7 +217,7 @@ class Pathname < String
|
|
228
217
|
def pstrip
|
229
218
|
str = self.dup
|
230
219
|
if @win
|
231
|
-
|
220
|
+
PathRemoveBackslash(str)
|
232
221
|
str.strip!
|
233
222
|
else
|
234
223
|
if str[-1].chr == @sep
|
@@ -243,7 +232,7 @@ class Pathname < String
|
|
243
232
|
#
|
244
233
|
def pstrip!
|
245
234
|
if @win
|
246
|
-
|
235
|
+
PathRemoveBackslash(self)
|
247
236
|
strip!
|
248
237
|
else
|
249
238
|
if self[-1].chr == @sep
|
@@ -357,7 +346,7 @@ class Pathname < String
|
|
357
346
|
buf = 0.chr * MAX_PATH
|
358
347
|
buf[0..self.length-1] = self
|
359
348
|
|
360
|
-
if
|
349
|
+
if PathStripToRoot(buf)
|
361
350
|
dir = buf.split(0.chr).first
|
362
351
|
end
|
363
352
|
else
|
@@ -370,7 +359,7 @@ class Pathname < String
|
|
370
359
|
#
|
371
360
|
def root?
|
372
361
|
if @win
|
373
|
-
|
362
|
+
PathIsRoot(self)
|
374
363
|
else
|
375
364
|
self == root
|
376
365
|
end
|
@@ -386,7 +375,7 @@ class Pathname < String
|
|
386
375
|
raise NotImplementedError, "not supported on this platform"
|
387
376
|
end
|
388
377
|
|
389
|
-
|
378
|
+
PathIsUNC(self)
|
390
379
|
end
|
391
380
|
|
392
381
|
# Windows only
|
@@ -401,7 +390,7 @@ class Pathname < String
|
|
401
390
|
raise NotImplementedError, "not supported on this platform"
|
402
391
|
end
|
403
392
|
|
404
|
-
num =
|
393
|
+
num = PathGetDriveNumber(self)
|
405
394
|
num >= 0 ? num : nil
|
406
395
|
end
|
407
396
|
|
@@ -497,7 +486,7 @@ class Pathname < String
|
|
497
486
|
if @win
|
498
487
|
buf = 0.chr * MAX_PATH
|
499
488
|
buf[0..self.length-1] = self
|
500
|
-
|
489
|
+
PathAppend(buf, string)
|
501
490
|
buf = buf.split("\0").first
|
502
491
|
return self.class.new(buf) # PathAppend cleans automatically
|
503
492
|
end
|
@@ -515,6 +504,7 @@ class Pathname < String
|
|
515
504
|
|
516
505
|
self.class.new(new_string).clean
|
517
506
|
end
|
507
|
+
alias :/ :+
|
518
508
|
|
519
509
|
# Returns whether or not the path is an absolute path.
|
520
510
|
#
|
@@ -526,7 +516,7 @@ class Pathname < String
|
|
526
516
|
#
|
527
517
|
def relative?
|
528
518
|
if @win
|
529
|
-
|
519
|
+
PathIsRelative(self)
|
530
520
|
else
|
531
521
|
root == "."
|
532
522
|
end
|
@@ -540,7 +530,7 @@ class Pathname < String
|
|
540
530
|
|
541
531
|
if @win
|
542
532
|
path = 0.chr * MAX_PATH
|
543
|
-
if
|
533
|
+
if PathCanonicalize(path, self)
|
544
534
|
return self.class.new(path.split(0.chr).first)
|
545
535
|
else
|
546
536
|
return self
|
@@ -570,7 +560,7 @@ class Pathname < String
|
|
570
560
|
|
571
561
|
if @win
|
572
562
|
path = 0.chr * MAX_PATH
|
573
|
-
if
|
563
|
+
if PathCanonicalize(path, self)
|
574
564
|
replace(path.split(0.chr).first)
|
575
565
|
end
|
576
566
|
return self
|
@@ -861,3 +851,13 @@ class Pathname < String
|
|
861
851
|
FileUtils.copy_entry(self, *args)
|
862
852
|
end
|
863
853
|
end
|
854
|
+
|
855
|
+
module Kernel
|
856
|
+
# Usage: pn{ path }
|
857
|
+
#
|
858
|
+
# A shortcut for Pathname.new
|
859
|
+
#
|
860
|
+
def pn
|
861
|
+
instance_eval{ Pathname.new(yield) }
|
862
|
+
end
|
863
|
+
end
|
data/test/tc_pathname.rb
CHANGED
@@ -38,7 +38,7 @@ class TC_Pathname < Test::Unit::TestCase
|
|
38
38
|
@abs_array = []
|
39
39
|
@rel_array = []
|
40
40
|
|
41
|
-
@mypath = MyPathname.new('/usr/
|
41
|
+
@mypath = MyPathname.new('/usr/bin')
|
42
42
|
end
|
43
43
|
|
44
44
|
# Convenience method to verify that the receiver was not modified
|
@@ -77,7 +77,7 @@ class TC_Pathname < Test::Unit::TestCase
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def test_version
|
80
|
-
assert_equal('1.5.
|
80
|
+
assert_equal('1.5.1', Pathname::VERSION)
|
81
81
|
end
|
82
82
|
|
83
83
|
def test_file_url_path
|
@@ -88,7 +88,21 @@ class TC_Pathname < Test::Unit::TestCase
|
|
88
88
|
assert_respond_to(@abs_path, :realpath)
|
89
89
|
assert_equal(@pwd, Pathname.new('.').realpath)
|
90
90
|
assert_raises(Errno::ENOENT){ Pathname.new('../bogus').realpath }
|
91
|
+
assert_kind_of(Pathname, Pathname.new('/dev/stdin').realpath)
|
92
|
+
assert(Pathname.new('/dev/stdin') != Pathname.new('/dev/stdin').realpath)
|
93
|
+
end
|
91
94
|
|
95
|
+
def test_realpath_platform
|
96
|
+
case RUBY_PLATFORM
|
97
|
+
when /linux/i
|
98
|
+
path1 = '/dev/stdin'
|
99
|
+
assert_equal('/dev/pts/0', Pathname.new(path1).realpath)
|
100
|
+
when /sunos|solaris/i
|
101
|
+
path1 = '/dev/null'
|
102
|
+
path2 = '/dev/stdin'
|
103
|
+
assert_equal('/devices/pseudo/mm@0:null', Pathname.new(path1).realpath)
|
104
|
+
assert_equal('/dev/fd/0', Pathname.new(path2).realpath)
|
105
|
+
end
|
92
106
|
end
|
93
107
|
|
94
108
|
# These tests taken directly from Tanaka's pathname.rb. The one failure
|
@@ -347,6 +361,9 @@ class TC_Pathname < Test::Unit::TestCase
|
|
347
361
|
assert_pathname_plus('/', '/', '..')
|
348
362
|
assert_pathname_plus('.', '..', '..')
|
349
363
|
assert_pathname_plus('.', 'foo', '..')
|
364
|
+
|
365
|
+
# Alias
|
366
|
+
assert_equal('/foo/bar', Pathname.new('/foo') / Pathname.new('bar'))
|
350
367
|
end
|
351
368
|
|
352
369
|
# Any tests marked with '***' mean that this behavior is different than
|
@@ -417,12 +434,22 @@ class TC_Pathname < Test::Unit::TestCase
|
|
417
434
|
|
418
435
|
# Ensures that subclasses return the subclass as the class, not a hard
|
419
436
|
# coded Pathname.
|
437
|
+
#
|
420
438
|
def test_subclasses
|
421
439
|
assert_kind_of(MyPathname, @mypath)
|
422
440
|
assert_kind_of(MyPathname, @mypath + MyPathname.new('foo'))
|
423
441
|
assert_kind_of(MyPathname, @mypath.realpath)
|
424
442
|
assert_kind_of(MyPathname, @mypath.children.first)
|
425
443
|
end
|
444
|
+
|
445
|
+
# Test to ensure that the pn{ } shortcut works
|
446
|
+
#
|
447
|
+
def test_kernel_method
|
448
|
+
assert_respond_to(Kernel, :pn)
|
449
|
+
assert_nothing_raised{ pn{'/foo'} }
|
450
|
+
assert_kind_of(Pathname, pn{'/foo'})
|
451
|
+
assert_equal('/foo', pn{'/foo'})
|
452
|
+
end
|
426
453
|
|
427
454
|
def teardown
|
428
455
|
@pwd = nil
|
data/test/tc_pathname_win.rb
CHANGED
@@ -16,13 +16,14 @@ else
|
|
16
16
|
$LOAD_PATH.unshift Dir.pwd + "/lib"
|
17
17
|
end
|
18
18
|
|
19
|
-
unless
|
19
|
+
unless RUBY_PLATFORM.match("mswin")
|
20
20
|
STDERR.puts("Please run 'tc_pathname.rb' instead.")
|
21
21
|
exit
|
22
22
|
end
|
23
23
|
|
24
|
-
require
|
25
|
-
require
|
24
|
+
require 'facade' # Avoids annoying gems issue
|
25
|
+
require 'pathname2'
|
26
|
+
require 'test/unit'
|
26
27
|
|
27
28
|
class MyPathname < Pathname; end
|
28
29
|
|
@@ -55,7 +56,7 @@ class TC_Pathname_MSWin < Test::Unit::TestCase
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def test_version
|
58
|
-
assert_equal("1.5.
|
59
|
+
assert_equal("1.5.1", Pathname::VERSION)
|
59
60
|
end
|
60
61
|
|
61
62
|
# Convenience method for test_plus
|
@@ -624,6 +625,15 @@ class TC_Pathname_MSWin < Test::Unit::TestCase
|
|
624
625
|
assert_kind_of(MyPathname, @mypath.realpath)
|
625
626
|
assert_kind_of(MyPathname, @mypath.children.first)
|
626
627
|
end
|
628
|
+
|
629
|
+
# Test to ensure that the pn{ } shortcut works
|
630
|
+
#
|
631
|
+
def test_kernel_method
|
632
|
+
assert_respond_to(Kernel, :pn)
|
633
|
+
assert_nothing_raised{ pn{'c:\foo'} }
|
634
|
+
assert_kind_of(Pathname, pn{'c:\foo'})
|
635
|
+
assert_equal('c:\foo', pn{'c:\foo'})
|
636
|
+
end
|
627
637
|
|
628
638
|
def teardown
|
629
639
|
@fpath = nil
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: pathname2
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.5.
|
7
|
-
date: 2006-
|
6
|
+
version: 1.5.1
|
7
|
+
date: 2006-08-28 00:00:00 -06:00
|
8
8
|
summary: An alternate implementation of the Pathname class
|
9
9
|
require_paths:
|
10
|
-
|
10
|
+
- lib
|
11
11
|
email: djberg96@gmail.com
|
12
12
|
homepage: http://www.rubyforge.org/projects/shards
|
13
13
|
rubyforge_project:
|
@@ -18,40 +18,43 @@ bindir: bin
|
|
18
18
|
has_rdoc: true
|
19
19
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
20
|
requirements:
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
version: 0.0.0
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
25
24
|
version:
|
26
25
|
platform: ruby
|
27
26
|
signing_key:
|
28
27
|
cert_chain:
|
28
|
+
post_install_message:
|
29
29
|
authors:
|
30
|
-
|
30
|
+
- Daniel J. Berger
|
31
31
|
files:
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
- lib/pathname2.rb
|
33
|
+
- CHANGES
|
34
|
+
- MANIFEST
|
35
|
+
- README
|
36
|
+
- test/tc_pathname.rb
|
37
|
+
- test/tc_pathname_win.rb
|
38
38
|
test_files:
|
39
|
-
|
39
|
+
- test/tc_pathname.rb
|
40
40
|
rdoc_options: []
|
41
|
+
|
41
42
|
extra_rdoc_files:
|
42
|
-
|
43
|
-
|
43
|
+
- README
|
44
|
+
- CHANGES
|
44
45
|
executables: []
|
46
|
+
|
45
47
|
extensions: []
|
48
|
+
|
46
49
|
requirements: []
|
50
|
+
|
47
51
|
dependencies:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
version:
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: facade
|
54
|
+
version_requirement:
|
55
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.0.0
|
60
|
+
version:
|