pathname2 1.6.5-universal-mingw32 → 1.7.1-universal-mingw32
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.
- 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
|