pathname2 1.6.5-universal-mingw32 → 1.7.1-universal-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGES +10 -0
- data/MANIFEST +28 -1
- data/README +5 -6
- data/Rakefile +179 -3
- data/lib/pathname2.rb +128 -134
- data/pathname2.gemspec +7 -10
- data/test/test_pathname.rb +15 -18
- data/test/test_version.rb +13 -0
- data/test/windows/test_append.rb +59 -0
- data/test/windows/test_aref.rb +37 -0
- data/test/windows/test_ascend.rb +51 -0
- data/test/windows/test_children.rb +42 -0
- data/test/windows/test_clean.rb +50 -0
- data/test/windows/test_clean_bang.rb +50 -0
- data/test/windows/test_constructor.rb +48 -0
- data/test/windows/test_descend.rb +51 -0
- data/test/windows/test_drive_number.rb +58 -0
- data/test/windows/test_each.rb +28 -0
- data/test/windows/test_facade.rb +64 -0
- data/test/windows/test_is_absolute.rb +47 -0
- data/test/windows/test_is_relative.rb +46 -0
- data/test/windows/test_is_root.rb +44 -0
- data/test/windows/test_is_unc.rb +51 -0
- data/test/windows/test_long_path.rb +41 -0
- data/test/windows/test_misc.rb +33 -0
- data/test/windows/test_parent.rb +37 -0
- data/test/windows/test_pstrip.rb +42 -0
- data/test/windows/test_pstrip_bang.rb +46 -0
- data/test/windows/test_realpath.rb +39 -0
- data/test/windows/test_relative_path_from.rb +60 -0
- data/test/windows/test_root.rb +59 -0
- data/test/windows/test_short_path.rb +41 -0
- data/test/windows/test_to_a.rb +46 -0
- data/test/windows/test_undecorate.rb +47 -0
- data/test/windows/test_undecorate_bang.rb +53 -0
- metadata +137 -82
- data/test/test_pathname_windows.rb +0 -678
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NDcxYjA1NDMxNWUyNWYzNGZlOTE4NGJhNzM5NDUzNGFhNTZlMDY4Yg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YTM1ZGMwYzJlODBlM2E0OGUyZjZmZmJmOTE1ZjU5Y2IyMjk3NWJjOA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MWEwM2Y2ZGZlY2I0NjhhNzY2ZWNjZjRiMzE2ZTIwNGY2NGZmNmE0MTI2NmJh
|
10
|
+
Y2ZhNmJkZTRjOTIxZmZiYmRhMzcyYTk1YjQ2MzAyZDgyYjJlM2E0MjViMmVh
|
11
|
+
ZGY1MjZmM2NjZTViM2Y4N2IzYzFjZmQzZjQwOTUxNWY4OTVjZGQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YzMwMDNmMmI0YTdlZThhMTAxYWIzN2Y1OGQzM2FkYmQ4NzlmNjYyOTZkMWU0
|
14
|
+
Y2RmNWJjZDUyYTNkM2RlODJiNjVlMjA5ZGM1YTdlZTIwZjdhNjkyZjdkMzUx
|
15
|
+
ZTdlM2UyMzczMDYzYjgwNzJmMzNjOTcwMTE0Y2M0NGUzNmU3MzY=
|
data/CHANGES
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 1.7.1 - 28-Mar-2014
|
2
|
+
* Updated gemspec for Windows vs Unix.
|
3
|
+
* Updated README and MANIFEST.
|
4
|
+
|
5
|
+
== 1.7.0 - 28-Mar-2014
|
6
|
+
* Windows now uses FFI internally instead of win32-api.
|
7
|
+
* Added a custom pretty_print method for the pp library.
|
8
|
+
* Reorganized the test suite for Windows, and added many
|
9
|
+
more test tasks to the Rakefile.
|
10
|
+
|
1
11
|
== 1.6.5 - 19-Sep-2011
|
2
12
|
* Added the String#to_path instance method. This returns a Pathname
|
3
13
|
object.
|
data/MANIFEST
CHANGED
@@ -8,4 +8,31 @@
|
|
8
8
|
* examples/example_pathname.rb
|
9
9
|
* lib/pathname2.rb
|
10
10
|
* test/test_pathname.rb
|
11
|
-
* test/
|
11
|
+
* test/test_version.rb
|
12
|
+
* test/windows/test_append.rb
|
13
|
+
* test/windows/test_aref.rb
|
14
|
+
* test/windows/test_ascend.rb
|
15
|
+
* test/windows/test_children.rb
|
16
|
+
* test/windows/test_clean.rb
|
17
|
+
* test/windows/test_clean_bang.rb
|
18
|
+
* test/windows/test_constructor.rb
|
19
|
+
* test/windows/test_descend.rb
|
20
|
+
* test/windows/test_drive_number.rb
|
21
|
+
* test/windows/test_each.rb
|
22
|
+
* test/windows/test_facade.rb
|
23
|
+
* test/windows/test_is_absolute.rb
|
24
|
+
* test/windows/test_is_relative.rb
|
25
|
+
* test/windows/test_is_root.rb
|
26
|
+
* test/windows/test_is_unc.rb
|
27
|
+
* test/windows/test_long_path.rb
|
28
|
+
* test/windows/test_misc.rb
|
29
|
+
* test/windows/test_parent.rb
|
30
|
+
* test/windows/test_pstrip.rb
|
31
|
+
* test/windows/test_pstrip_bang.rb
|
32
|
+
* test/windows/test_realpath.rb
|
33
|
+
* test/windows/test_relative_path_from.rb
|
34
|
+
* test/windows/test_root.rb
|
35
|
+
* test/windows/test_short_path.rb
|
36
|
+
* test/windows/test_to_a.rb
|
37
|
+
* test/windows/test_undecorate.rb
|
38
|
+
* test/windows/test_undecorate_bang.rb
|
data/README
CHANGED
@@ -2,8 +2,9 @@
|
|
2
2
|
A drop-in replacement for the current Pathname class.
|
3
3
|
|
4
4
|
== Prerequisites
|
5
|
-
* facade
|
6
|
-
*
|
5
|
+
* facade
|
6
|
+
* ffi (Windows only)
|
7
|
+
* test-unit (testing only)
|
7
8
|
|
8
9
|
== Installation
|
9
10
|
|
@@ -76,9 +77,7 @@
|
|
76
77
|
supposed to be private. See ruby-core:7383.
|
77
78
|
|
78
79
|
Any other issues should be reported on the project page at
|
79
|
-
|
80
|
-
|
81
|
-
The git repo itself is located at https://github.com/djberg96/pathname2
|
80
|
+
https://github.com/djberg96/pathname2
|
82
81
|
|
83
82
|
== Future Plans
|
84
83
|
Suggestions welcome.
|
@@ -87,7 +86,7 @@
|
|
87
86
|
Artistic 2.0
|
88
87
|
|
89
88
|
== Copyright
|
90
|
-
(C) 2003-
|
89
|
+
(C) 2003-2014 Daniel J. Berger
|
91
90
|
All rights reserved.
|
92
91
|
|
93
92
|
== Warranty
|
data/Rakefile
CHANGED
@@ -8,7 +8,12 @@ namespace :gem do
|
|
8
8
|
desc "Build the pathname2 gem"
|
9
9
|
task :create => [:clean] do
|
10
10
|
spec = eval(IO.read('pathname2.gemspec'))
|
11
|
-
Gem::
|
11
|
+
if Gem::VERSION < "2.0"
|
12
|
+
Gem::Builder.new(spec).build
|
13
|
+
else
|
14
|
+
require 'rubygems/package'
|
15
|
+
Gem::Package.build(spec)
|
16
|
+
end
|
12
17
|
end
|
13
18
|
|
14
19
|
desc "Install the pathname2 gem"
|
@@ -23,13 +28,184 @@ Rake::TestTask.new('test') do |t|
|
|
23
28
|
t.warning = true
|
24
29
|
t.verbose = true
|
25
30
|
|
26
|
-
if
|
27
|
-
t.test_files = FileList[
|
31
|
+
if File::ALT_SEPARATOR
|
32
|
+
t.test_files = FileList["test/windows/*.rb"] + FileList["test/test_version.rb"]
|
28
33
|
else
|
29
34
|
t.test_files = FileList['test/test_pathname.rb']
|
30
35
|
end
|
31
36
|
end
|
32
37
|
|
38
|
+
namespace :test do
|
39
|
+
dir = File::ALT_SEPARATOR ? "windows" : "unix"
|
40
|
+
Rake::TestTask.new(:all) do |t|
|
41
|
+
t.warning = true
|
42
|
+
t.verbose = true
|
43
|
+
t.test_files = FileList["test/#{dir}/*.rb"] + FileList["test/test_version.rb"]
|
44
|
+
end
|
45
|
+
|
46
|
+
Rake::TestTask.new(:append) do |t|
|
47
|
+
t.warning = true
|
48
|
+
t.verbose = true
|
49
|
+
t.test_files = FileList["test/#{dir}/test_append.rb"]
|
50
|
+
end
|
51
|
+
|
52
|
+
Rake::TestTask.new(:aref) do |t|
|
53
|
+
t.warning = true
|
54
|
+
t.verbose = true
|
55
|
+
t.test_files = FileList["test/#{dir}/test_aref.rb"]
|
56
|
+
end
|
57
|
+
|
58
|
+
Rake::TestTask.new(:ascend) do |t|
|
59
|
+
t.warning = true
|
60
|
+
t.verbose = true
|
61
|
+
t.test_files = FileList["test/#{dir}/test_ascend.rb"]
|
62
|
+
end
|
63
|
+
|
64
|
+
Rake::TestTask.new(:children) do |t|
|
65
|
+
t.warning = true
|
66
|
+
t.verbose = true
|
67
|
+
t.test_files = FileList["test/#{dir}/test_children.rb"]
|
68
|
+
end
|
69
|
+
|
70
|
+
Rake::TestTask.new(:clean) do |t|
|
71
|
+
t.warning = true
|
72
|
+
t.verbose = true
|
73
|
+
t.test_files = FileList["test/#{dir}/test_clean.rb"]
|
74
|
+
end
|
75
|
+
|
76
|
+
Rake::TestTask.new(:clean!) do |t|
|
77
|
+
t.warning = true
|
78
|
+
t.verbose = true
|
79
|
+
t.test_files = FileList["test/#{dir}/test_clean_bang.rb"]
|
80
|
+
end
|
81
|
+
|
82
|
+
Rake::TestTask.new(:constructor) do |t|
|
83
|
+
t.warning = true
|
84
|
+
t.verbose = true
|
85
|
+
t.test_files = FileList["test/#{dir}/test_constructor.rb"]
|
86
|
+
end
|
87
|
+
|
88
|
+
Rake::TestTask.new(:descend) do |t|
|
89
|
+
t.warning = true
|
90
|
+
t.verbose = true
|
91
|
+
t.test_files = FileList["test/#{dir}/test_descend.rb"]
|
92
|
+
end
|
93
|
+
|
94
|
+
Rake::TestTask.new(:drive_number) do |t|
|
95
|
+
t.warning = true
|
96
|
+
t.verbose = true
|
97
|
+
t.test_files = FileList["test/#{dir}/test_drive_number.rb"]
|
98
|
+
end
|
99
|
+
|
100
|
+
Rake::TestTask.new(:each) do |t|
|
101
|
+
t.warning = true
|
102
|
+
t.verbose = true
|
103
|
+
t.test_files = FileList["test/#{dir}/test_each.rb"]
|
104
|
+
end
|
105
|
+
|
106
|
+
Rake::TestTask.new(:facade) do |t|
|
107
|
+
t.warning = true
|
108
|
+
t.verbose = true
|
109
|
+
t.test_files = FileList["test/#{dir}/test_facade.rb"]
|
110
|
+
end
|
111
|
+
|
112
|
+
Rake::TestTask.new(:is_absolute) do |t|
|
113
|
+
t.warning = true
|
114
|
+
t.verbose = true
|
115
|
+
t.test_files = FileList["test/#{dir}/test_is_absolute.rb"]
|
116
|
+
end
|
117
|
+
|
118
|
+
Rake::TestTask.new(:is_relative) do |t|
|
119
|
+
t.warning = true
|
120
|
+
t.verbose = true
|
121
|
+
t.test_files = FileList["test/#{dir}/test_is_relative.rb"]
|
122
|
+
end
|
123
|
+
|
124
|
+
Rake::TestTask.new(:is_root) do |t|
|
125
|
+
t.warning = true
|
126
|
+
t.verbose = true
|
127
|
+
t.test_files = FileList["test/#{dir}/test_is_root.rb"]
|
128
|
+
end
|
129
|
+
|
130
|
+
Rake::TestTask.new(:is_unc) do |t|
|
131
|
+
t.warning = true
|
132
|
+
t.verbose = true
|
133
|
+
t.test_files = FileList["test/#{dir}/test_is_unc.rb"]
|
134
|
+
end
|
135
|
+
|
136
|
+
Rake::TestTask.new(:long_path) do |t|
|
137
|
+
t.warning = true
|
138
|
+
t.verbose = true
|
139
|
+
t.test_files = FileList["test/#{dir}/test_long_path.rb"]
|
140
|
+
end
|
141
|
+
|
142
|
+
Rake::TestTask.new(:misc) do |t|
|
143
|
+
t.warning = true
|
144
|
+
t.verbose = true
|
145
|
+
t.test_files = FileList["test/#{dir}/test_misc.rb"]
|
146
|
+
end
|
147
|
+
|
148
|
+
Rake::TestTask.new(:parent) do |t|
|
149
|
+
t.warning = true
|
150
|
+
t.verbose = true
|
151
|
+
t.test_files = FileList["test/#{dir}/test_parent.rb"]
|
152
|
+
end
|
153
|
+
|
154
|
+
Rake::TestTask.new(:pstrip) do |t|
|
155
|
+
t.warning = true
|
156
|
+
t.verbose = true
|
157
|
+
t.test_files = FileList["test/#{dir}/test_pstrip.rb"]
|
158
|
+
end
|
159
|
+
|
160
|
+
Rake::TestTask.new(:pstrip!) do |t|
|
161
|
+
t.warning = true
|
162
|
+
t.verbose = true
|
163
|
+
t.test_files = FileList["test/#{dir}/test_pstrip_bang.rb"]
|
164
|
+
end
|
165
|
+
|
166
|
+
Rake::TestTask.new(:realpath) do |t|
|
167
|
+
t.warning = true
|
168
|
+
t.verbose = true
|
169
|
+
t.test_files = FileList["test/#{dir}/test_realpath.rb"]
|
170
|
+
end
|
171
|
+
|
172
|
+
Rake::TestTask.new(:relative_path_from) do |t|
|
173
|
+
t.warning = true
|
174
|
+
t.verbose = true
|
175
|
+
t.test_files = FileList["test/#{dir}/test_relative_path_from.rb"]
|
176
|
+
end
|
177
|
+
|
178
|
+
Rake::TestTask.new(:root) do |t|
|
179
|
+
t.warning = true
|
180
|
+
t.verbose = true
|
181
|
+
t.test_files = FileList["test/#{dir}/test_root.rb"]
|
182
|
+
end
|
183
|
+
|
184
|
+
Rake::TestTask.new(:short_path) do |t|
|
185
|
+
t.warning = true
|
186
|
+
t.verbose = true
|
187
|
+
t.test_files = FileList["test/#{dir}/test_short_path.rb"]
|
188
|
+
end
|
189
|
+
|
190
|
+
Rake::TestTask.new(:to_a) do |t|
|
191
|
+
t.warning = true
|
192
|
+
t.verbose = true
|
193
|
+
t.test_files = FileList["test/#{dir}/test_to_a.rb"]
|
194
|
+
end
|
195
|
+
|
196
|
+
Rake::TestTask.new(:undecorate) do |t|
|
197
|
+
t.warning = true
|
198
|
+
t.verbose = true
|
199
|
+
t.test_files = FileList["test/#{dir}/test_undecorate.rb"]
|
200
|
+
end
|
201
|
+
|
202
|
+
Rake::TestTask.new(:undecorate!) do |t|
|
203
|
+
t.warning = true
|
204
|
+
t.verbose = true
|
205
|
+
t.test_files = FileList["test/#{dir}/test_undecorate_bang.rb"]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
33
209
|
desc 'Run the Pathname benchmark suite'
|
34
210
|
task :benchmark do
|
35
211
|
sh 'ruby -Ilib benchmarks/bench_pathname.rb'
|
data/lib/pathname2.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# == Synopsis
|
2
2
|
#
|
3
|
-
# Pathname represents a path name on a filesystem.
|
3
|
+
# Pathname represents a path name on a filesystem. A Pathname can be
|
4
4
|
# relative or absolute. It does not matter whether the path exists or not.
|
5
5
|
#
|
6
6
|
# All functionality from File, FileTest, and Dir is included, using a facade
|
7
7
|
# pattern.
|
8
8
|
#
|
9
|
-
# This class works on both Unix and Windows, including UNC path names.
|
9
|
+
# This class works on both Unix and Windows, including UNC path names. Note
|
10
10
|
# that forward slashes are converted to backslashes on Windows systems.
|
11
11
|
#
|
12
12
|
# == Usage
|
@@ -27,24 +27,22 @@
|
|
27
27
|
# path1 + path2 # "C:\\foo\\bar\\zap"
|
28
28
|
# path1.exists? # Does the path exist?
|
29
29
|
#
|
30
|
-
# == Author
|
31
|
-
#
|
32
|
-
# Daniel J. Berger
|
33
|
-
# djberg96 at gmail dot com
|
34
|
-
# imperator on IRC (irc.freenode.net)
|
35
|
-
#
|
36
|
-
# == Copyright
|
37
|
-
# Copyright (c) 2005-2011 Daniel J. Berger.
|
38
|
-
# Licensed under the same terms as Ruby itself.
|
39
|
-
#
|
40
30
|
require 'facade'
|
41
31
|
require 'fileutils'
|
32
|
+
require 'pp'
|
42
33
|
|
43
34
|
if File::ALT_SEPARATOR
|
44
|
-
require '
|
45
|
-
|
46
|
-
|
47
|
-
|
35
|
+
require 'ffi'
|
36
|
+
class String
|
37
|
+
# Convenience method for converting strings to UTF-16LE for wide character
|
38
|
+
# functions that require it.
|
39
|
+
def wincode
|
40
|
+
if self.encoding.name != 'UTF-16LE'
|
41
|
+
temp = self.dup
|
42
|
+
(temp.tr(File::SEPARATOR, File::ALT_SEPARATOR) << 0.chr).encode('UTF-16LE')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
48
46
|
end
|
49
47
|
|
50
48
|
# You're mine now.
|
@@ -54,6 +52,8 @@ class Pathname < String
|
|
54
52
|
class Error < StandardError; end
|
55
53
|
extend Facade
|
56
54
|
|
55
|
+
undef_method :pretty_print
|
56
|
+
|
57
57
|
facade File, File.methods(false).map{ |m| m.to_sym } - [
|
58
58
|
:chmod, :lchmod, :chown, :lchown, :dirname, :fnmatch, :fnmatch?,
|
59
59
|
:link, :open, :realpath, :rename, :symlink, :truncate, :utime,
|
@@ -69,16 +69,31 @@ class Pathname < String
|
|
69
69
|
alias :_plus_ :+ # Used to prevent infinite loops in some cases
|
70
70
|
|
71
71
|
if File::ALT_SEPARATOR
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
extend FFI::Library
|
73
|
+
ffi_lib :shlwapi
|
74
|
+
|
75
|
+
attach_function :PathAppendW, [:pointer, :pointer], :bool
|
76
|
+
attach_function :PathCanonicalizeW, [:pointer, :buffer_in], :bool
|
77
|
+
attach_function :PathCreateFromUrlW, [:buffer_in, :pointer, :pointer, :ulong], :long
|
78
|
+
attach_function :PathGetDriveNumberW, [:buffer_in], :int
|
79
|
+
attach_function :PathIsRelativeW, [:buffer_in], :bool
|
80
|
+
attach_function :PathIsRootW, [:buffer_in], :bool
|
81
|
+
attach_function :PathIsUNCW, [:buffer_in], :bool
|
82
|
+
attach_function :PathIsURLW, [:buffer_in], :bool
|
83
|
+
attach_function :PathRemoveBackslashW, [:buffer_in], :pointer
|
84
|
+
attach_function :PathStripToRootW, [:pointer], :bool
|
85
|
+
attach_function :PathUndecorateW, [:pointer], :void
|
86
|
+
|
87
|
+
ffi_lib :kernel32
|
88
|
+
|
89
|
+
attach_function :GetLongPathNameW, [:buffer_in, :buffer_out, :ulong], :ulong
|
90
|
+
attach_function :GetShortPathNameW, [:buffer_in, :pointer, :ulong], :ulong
|
76
91
|
end
|
77
92
|
|
78
93
|
public
|
79
94
|
|
80
95
|
# The version of the pathname2 library
|
81
|
-
VERSION = '1.
|
96
|
+
VERSION = '1.7.1'
|
82
97
|
|
83
98
|
# The maximum length of a path
|
84
99
|
MAXPATH = 1024 unless defined? MAXPATH # Yes, I willfully violate POSIX
|
@@ -102,8 +117,7 @@ class Pathname < String
|
|
102
117
|
# example, all forward slashes are replaced with backslashes.
|
103
118
|
#
|
104
119
|
# File URL's will be converted to Pathname objects, e.g. the file URL
|
105
|
-
# "file:///C:/Documents%20and%20Settings" will become
|
106
|
-
# 'C:\Documents and Settings'.
|
120
|
+
# "file:///C:/Documents%20and%20Settings" will become 'C:\Documents and Settings'.
|
107
121
|
#
|
108
122
|
# Examples:
|
109
123
|
#
|
@@ -115,7 +129,7 @@ class Pathname < String
|
|
115
129
|
def initialize(path)
|
116
130
|
if path.length > MAXPATH
|
117
131
|
msg = "string too long. maximum string length is " + MAXPATH.to_s
|
118
|
-
raise
|
132
|
+
raise ArgumentError, msg
|
119
133
|
end
|
120
134
|
|
121
135
|
@sep = File::ALT_SEPARATOR || File::SEPARATOR
|
@@ -125,11 +139,15 @@ class Pathname < String
|
|
125
139
|
# because Ruby's URI class does not (currently) parse absolute file URL's
|
126
140
|
# properly when they include a drive letter.
|
127
141
|
if @win
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
142
|
+
wpath = path.wincode
|
143
|
+
|
144
|
+
if PathIsURLW(wpath)
|
145
|
+
buf = FFI::MemoryPointer.new(:char, MAXPATH)
|
146
|
+
len = FFI::MemoryPointer.new(:ulong)
|
147
|
+
len.write_ulong(buf.size)
|
148
|
+
|
149
|
+
if PathCreateFromUrlW(wpath, buf, len, 0) == 0
|
150
|
+
path = buf.read_string(path.size * 2).tr(0.chr, '')
|
133
151
|
else
|
134
152
|
raise Error, "invalid file url: #{path}"
|
135
153
|
end
|
@@ -137,16 +155,13 @@ class Pathname < String
|
|
137
155
|
else
|
138
156
|
if path.index('file:///', 0)
|
139
157
|
require 'uri'
|
140
|
-
|
141
|
-
path = URI::Parser.new.unescape(path)[7..-1] # Blech
|
142
|
-
else
|
143
|
-
path = URI.decode(URI.parse(path).path)
|
144
|
-
end
|
158
|
+
path = URI::Parser.new.unescape(path)[7..-1]
|
145
159
|
end
|
146
160
|
end
|
147
161
|
|
148
162
|
# Convert forward slashes to backslashes on Windows
|
149
|
-
path = path.tr(
|
163
|
+
path = path.tr(File::SEPARATOR, File::ALT_SEPARATOR) if @win
|
164
|
+
|
150
165
|
super(path)
|
151
166
|
end
|
152
167
|
|
@@ -184,7 +199,7 @@ class Pathname < String
|
|
184
199
|
# the returned pathnames will contain the filename only.
|
185
200
|
#
|
186
201
|
# Note that the result never contain the entries '.' and '..' in the
|
187
|
-
# the directory because they are not children.
|
202
|
+
# the directory because they are not children. Also note that this method
|
188
203
|
# is *not* recursive.
|
189
204
|
#
|
190
205
|
# Example:
|
@@ -220,10 +235,12 @@ class Pathname < String
|
|
220
235
|
unless @win
|
221
236
|
raise NotImplementedError, "not supported on this platform"
|
222
237
|
end
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
238
|
+
|
239
|
+
wpath = FFI::MemoryPointer.from_string(self.wincode)
|
240
|
+
|
241
|
+
PathUndecorateW(wpath)
|
242
|
+
|
243
|
+
self.class.new(wpath.read_string(wpath.size).split("\000\000").first.tr(0.chr, ''))
|
227
244
|
end
|
228
245
|
|
229
246
|
# Windows only
|
@@ -231,14 +248,7 @@ class Pathname < String
|
|
231
248
|
# Performs the substitution of Pathname#undecorate in place.
|
232
249
|
#
|
233
250
|
def undecorate!
|
234
|
-
|
235
|
-
raise NotImplementedError, "not supported on this platform"
|
236
|
-
end
|
237
|
-
buf = 0.chr * MAXPATH
|
238
|
-
buf[0..self.length-1] = self
|
239
|
-
PathUndecorate(buf)
|
240
|
-
replace(buf.split(0.chr).first)
|
241
|
-
self
|
251
|
+
self.replace(undecorate)
|
242
252
|
end
|
243
253
|
|
244
254
|
# Windows only
|
@@ -251,13 +261,16 @@ class Pathname < String
|
|
251
261
|
# path.short_path # => C:\Progra~1\Java.
|
252
262
|
#
|
253
263
|
def short_path
|
254
|
-
unless @win
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
264
|
+
raise NotImplementedError, "not supported on this platform" unless @win
|
265
|
+
|
266
|
+
buf = FFI::MemoryPointer.new(:char, MAXPATH)
|
267
|
+
wpath = self.wincode
|
268
|
+
|
269
|
+
size = GetShortPathNameW(wpath, buf, buf.size)
|
270
|
+
|
271
|
+
raise SystemCallError.new('GetShortPathName', FFI.errno) if size == 0
|
272
|
+
|
273
|
+
self.class.new(buf.read_bytes(size * 2).delete(0.chr))
|
261
274
|
end
|
262
275
|
|
263
276
|
# Windows only
|
@@ -270,16 +283,19 @@ class Pathname < String
|
|
270
283
|
# path.long_path # => C:\Program Files\Java.
|
271
284
|
#
|
272
285
|
def long_path
|
273
|
-
unless @win
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
286
|
+
raise NotImplementedError, "not supported on this platform" unless @win
|
287
|
+
|
288
|
+
buf = FFI::MemoryPointer.new(:char, MAXPATH)
|
289
|
+
wpath = self.wincode
|
290
|
+
|
291
|
+
size = GetLongPathNameW(wpath, buf, buf.size)
|
292
|
+
|
293
|
+
raise SystemCallError.new('GetShortPathName', FFI.errno) if size == 0
|
294
|
+
|
295
|
+
self.class.new(buf.read_bytes(size * 2).delete(0.chr))
|
280
296
|
end
|
281
297
|
|
282
|
-
# Removes trailing
|
298
|
+
# Removes all trailing slashes, if present. Non-destructive.
|
283
299
|
#
|
284
300
|
# Example:
|
285
301
|
#
|
@@ -288,31 +304,20 @@ class Pathname < String
|
|
288
304
|
#
|
289
305
|
def pstrip
|
290
306
|
str = self.dup
|
291
|
-
if
|
292
|
-
|
307
|
+
return str if str.empty?
|
308
|
+
|
309
|
+
while ["/", "\\"].include?(str.to_s[-1].chr)
|
293
310
|
str.strip!
|
294
|
-
|
295
|
-
if str.to_s[-1].chr == @sep
|
296
|
-
str.strip!
|
297
|
-
str.chop!
|
298
|
-
end
|
311
|
+
str.chop!
|
299
312
|
end
|
313
|
+
|
300
314
|
self.class.new(str)
|
301
315
|
end
|
302
316
|
|
303
317
|
# Performs the substitution of Pathname#pstrip in place.
|
304
318
|
#
|
305
319
|
def pstrip!
|
306
|
-
|
307
|
-
PathRemoveBackslash(self)
|
308
|
-
strip!
|
309
|
-
else
|
310
|
-
if self.to_s[-1].chr == @sep
|
311
|
-
strip!
|
312
|
-
chop!
|
313
|
-
end
|
314
|
-
end
|
315
|
-
self
|
320
|
+
self.replace(pstrip)
|
316
321
|
end
|
317
322
|
|
318
323
|
# Splits a pathname into strings based on the path separator.
|
@@ -323,7 +328,12 @@ class Pathname < String
|
|
323
328
|
# Pathname.new('C:\WINNT\Fonts').to_a # => ['C:', 'WINNT', 'Fonts']
|
324
329
|
#
|
325
330
|
def to_a
|
326
|
-
|
331
|
+
# Split string by path separator
|
332
|
+
if @win
|
333
|
+
array = tr(File::SEPARATOR, File::ALT_SEPARATOR).split(@sep)
|
334
|
+
else
|
335
|
+
array = split(@sep)
|
336
|
+
end
|
327
337
|
array.delete("") # Remove empty elements
|
328
338
|
array
|
329
339
|
end
|
@@ -481,7 +491,7 @@ class Pathname < String
|
|
481
491
|
# Returns the root directory of the path, or '.' if there is no root
|
482
492
|
# directory.
|
483
493
|
#
|
484
|
-
# On Unix, this means the '/' character.
|
494
|
+
# On Unix, this means the '/' character. On Windows, this can refer
|
485
495
|
# to the drive letter, or the server and share path if the path is a
|
486
496
|
# UNC path.
|
487
497
|
#
|
@@ -499,11 +509,9 @@ class Pathname < String
|
|
499
509
|
dir = "."
|
500
510
|
|
501
511
|
if @win
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
if PathStripToRoot(buf)
|
506
|
-
dir = buf.split(0.chr).first
|
512
|
+
wpath = FFI::MemoryPointer.from_string(self.wincode)
|
513
|
+
if PathStripToRootW(wpath)
|
514
|
+
dir = wpath.read_string(wpath.size).split("\000\000").first.tr(0.chr, '')
|
507
515
|
end
|
508
516
|
else
|
509
517
|
dir = "/" if self =~ /^\//
|
@@ -521,7 +529,7 @@ class Pathname < String
|
|
521
529
|
#
|
522
530
|
def root?
|
523
531
|
if @win
|
524
|
-
|
532
|
+
PathIsRootW(self.wincode)
|
525
533
|
else
|
526
534
|
self == root
|
527
535
|
end
|
@@ -538,11 +546,8 @@ class Pathname < String
|
|
538
546
|
# Pathname.new('C:\Program Files').unc? # => false
|
539
547
|
#
|
540
548
|
def unc?
|
541
|
-
unless @win
|
542
|
-
|
543
|
-
end
|
544
|
-
|
545
|
-
PathIsUNC(self)
|
549
|
+
raise NotImplementedError, "not supported on this platform" unless @win
|
550
|
+
PathIsUNCW(self.wincode)
|
546
551
|
end
|
547
552
|
|
548
553
|
# MS Windows only
|
@@ -559,12 +564,12 @@ class Pathname < String
|
|
559
564
|
raise NotImplementedError, "not supported on this platform"
|
560
565
|
end
|
561
566
|
|
562
|
-
num =
|
567
|
+
num = PathGetDriveNumberW(self.wincode)
|
563
568
|
num >= 0 ? num : nil
|
564
569
|
end
|
565
570
|
|
566
571
|
# Compares two Pathname objects. Note that Pathnames may only be compared
|
567
|
-
# against other Pathnames, not strings.
|
572
|
+
# against other Pathnames, not strings. Otherwise nil is returned.
|
568
573
|
#
|
569
574
|
# Example:
|
570
575
|
#
|
@@ -587,7 +592,8 @@ class Pathname < String
|
|
587
592
|
# Pathname.new('/usr/local/bin').parent # => '/usr/local'
|
588
593
|
#
|
589
594
|
def parent
|
590
|
-
|
595
|
+
return self if root?
|
596
|
+
self + ".." # Use our custom '+' method
|
591
597
|
end
|
592
598
|
|
593
599
|
# Returns a relative path from the argument to the receiver. If +self+
|
@@ -636,7 +642,7 @@ class Pathname < String
|
|
636
642
|
dest_arr.delete('.')
|
637
643
|
base_arr.delete('.')
|
638
644
|
|
639
|
-
diff_arr = dest_arr - base_arr
|
645
|
+
# diff_arr = dest_arr - base_arr
|
640
646
|
|
641
647
|
while !base_arr.empty? && !dest_arr.empty? && base_arr[0] == dest_arr[0]
|
642
648
|
base_arr.shift
|
@@ -657,11 +663,11 @@ class Pathname < String
|
|
657
663
|
end
|
658
664
|
end
|
659
665
|
|
660
|
-
# Adds two Pathname objects together, or a Pathname and a String.
|
666
|
+
# Adds two Pathname objects together, or a Pathname and a String. It
|
661
667
|
# also automatically cleans the Pathname.
|
662
668
|
#
|
663
669
|
# Adding a root path to an existing path merely replaces the current
|
664
|
-
# path.
|
670
|
+
# path. Adding '.' to an existing path does nothing.
|
665
671
|
#
|
666
672
|
# Example:
|
667
673
|
#
|
@@ -680,11 +686,15 @@ class Pathname < String
|
|
680
686
|
|
681
687
|
# Use the builtin PathAppend() function if on Windows - much easier
|
682
688
|
if @win
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
689
|
+
path = FFI::MemoryPointer.new(:char, MAXPATH)
|
690
|
+
path.write_string(self.dup.wincode)
|
691
|
+
more = FFI::MemoryPointer.from_string(string.wincode)
|
692
|
+
|
693
|
+
PathAppendW(path, more)
|
694
|
+
|
695
|
+
path = path.read_string(path.size).split("\000\000").first.delete(0.chr)
|
696
|
+
|
697
|
+
return self.class.new(path) # PathAppend cleans automatically
|
688
698
|
end
|
689
699
|
|
690
700
|
# If the string is an absolute directory, return it
|
@@ -723,7 +733,7 @@ class Pathname < String
|
|
723
733
|
#
|
724
734
|
def relative?
|
725
735
|
if @win
|
726
|
-
|
736
|
+
PathIsRelativeW(self.wincode)
|
727
737
|
else
|
728
738
|
root == "."
|
729
739
|
end
|
@@ -741,9 +751,9 @@ class Pathname < String
|
|
741
751
|
return self if self.empty?
|
742
752
|
|
743
753
|
if @win
|
744
|
-
|
745
|
-
if
|
746
|
-
return self.class.new(
|
754
|
+
ptr = FFI::MemoryPointer.new(:char, MAXPATH)
|
755
|
+
if PathCanonicalizeW(ptr, self.wincode)
|
756
|
+
return self.class.new(ptr.read_string(ptr.size).delete(0.chr))
|
747
757
|
else
|
748
758
|
return self
|
749
759
|
end
|
@@ -772,32 +782,7 @@ class Pathname < String
|
|
772
782
|
# in place.
|
773
783
|
#
|
774
784
|
def clean!
|
775
|
-
|
776
|
-
|
777
|
-
if @win
|
778
|
-
path = 0.chr * MAXPATH
|
779
|
-
if PathCanonicalize(path, self)
|
780
|
-
replace(path.split(0.chr).first)
|
781
|
-
end
|
782
|
-
return self
|
783
|
-
end
|
784
|
-
|
785
|
-
final = []
|
786
|
-
|
787
|
-
to_a.each{ |element|
|
788
|
-
next if element == "."
|
789
|
-
final.push(element)
|
790
|
-
if element == ".." && self != ".."
|
791
|
-
2.times{ final.pop }
|
792
|
-
end
|
793
|
-
}
|
794
|
-
|
795
|
-
final = final.join(@sep)
|
796
|
-
final = root + final if root != "."
|
797
|
-
final = "." if final.empty?
|
798
|
-
replace(self.class.new(final))
|
799
|
-
|
800
|
-
self
|
785
|
+
self.replace(clean)
|
801
786
|
end
|
802
787
|
|
803
788
|
alias cleanpath! clean!
|
@@ -828,6 +813,15 @@ class Pathname < String
|
|
828
813
|
local_path
|
829
814
|
end
|
830
815
|
|
816
|
+
# A custom pretty printer
|
817
|
+
def pretty_print(q)
|
818
|
+
if File::ALT_SEPARATOR
|
819
|
+
q.text(self.to_s.tr(File::SEPARATOR, File::ALT_SEPARATOR))
|
820
|
+
else
|
821
|
+
q.text(self.to_s)
|
822
|
+
end
|
823
|
+
end
|
824
|
+
|
831
825
|
#-- Find facade
|
832
826
|
|
833
827
|
# Pathname#find is an iterator to traverse a directory tree in a depth first
|