recls-ruby 2.13.0.1 → 2.13.2
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 +4 -4
- data/lib/recls/combine_paths_1.rb +28 -4
- data/lib/recls/combine_paths_2plus.rb +28 -4
- data/lib/recls/entry.rb +17 -6
- data/lib/recls/version.rb +2 -2
- data/lib/recls/ximpl/util.rb +1 -1
- data/lib/recls/ximpl/windows.rb +170 -54
- data/test/unit/tc_recls_entry.rb +18 -1
- data/test/unit/tc_recls_util.rb +0 -109
- data/test/unit/util/tc_combine_paths.rb +158 -0
- data/test/unit/util/ts_all.rb +22 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59eb42b0b882edabe96abf491f8a44947a84c8a2b721a16d0a1c785d4037397e
|
4
|
+
data.tar.gz: 51f05e185bf3e51a3c1badf5653431ee2d8e554f8d298a191b60f813b73022c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b627bb5850d768f90001ff0192b0b1f8f2d09d04d9a3fd04ae96952297056b8728a68592205c39158647c6564ba450872623c14899c09f3c87dd99dda122ec9a
|
7
|
+
data.tar.gz: 74a224e1269bd4484a794a02f165b65138437b8790038cb3156f4147c4f66b08f7bfe29990228ae050be6bf89a504c487c79ccc8d2451fa496e6aa86f79cafa8
|
@@ -4,11 +4,11 @@
|
|
4
4
|
# Purpose: Definition of Recls::compare_paths() for Ruby 1.x
|
5
5
|
#
|
6
6
|
# Created: 17th February 2014
|
7
|
-
# Updated:
|
7
|
+
# Updated: 9th January 2025
|
8
8
|
#
|
9
9
|
# Author: Matthew Wilson
|
10
10
|
#
|
11
|
-
# Copyright (c) 2019-
|
11
|
+
# Copyright (c) 2019-2025, Matthew Wilson and Synesis Information Systems
|
12
12
|
# Copyright (c) 2014-2019, Matthew Wilson and Synesis Software
|
13
13
|
# All rights reserved.
|
14
14
|
#
|
@@ -45,7 +45,16 @@ require 'recls/ximpl/util'
|
|
45
45
|
|
46
46
|
module Recls
|
47
47
|
|
48
|
-
# Combines paths
|
48
|
+
# Combines paths, optionally canonicalising them.
|
49
|
+
#
|
50
|
+
# Unlike `File::join()`, this method takes account of relative vs absolute
|
51
|
+
# elements in the sequence. Specifically, the rightmost non-relative
|
52
|
+
# element, if it exists, anchors the combination, such that any arguments
|
53
|
+
# to the left are ignored. Furthermore, any entries (of type
|
54
|
+
# `Recls::Entry`) in the sequence are given special treatment as follows:
|
55
|
+
# - a rightmost `#file?` or `#device?` is returned as the complete result;
|
56
|
+
# - a rightmost `#directory?` causes all prior elements to be ignored and
|
57
|
+
# may be combined with subsequent elements;
|
49
58
|
#
|
50
59
|
# === Signature
|
51
60
|
#
|
@@ -60,7 +69,22 @@ module Recls
|
|
60
69
|
|
61
70
|
raise ArgumentError, 'must specify one or more path elements' if paths.empty?
|
62
71
|
|
63
|
-
ix_last_entry = paths.rindex { |path| ::Recls::Entry === path }
|
72
|
+
ix_last_entry = paths.rindex { |path| ::Recls::Entry === path }
|
73
|
+
|
74
|
+
if ix_last_entry
|
75
|
+
|
76
|
+
fe = paths[ix_last_entry]
|
77
|
+
|
78
|
+
if fe.directory?
|
79
|
+
|
80
|
+
paths = paths[ix_last_entry..]
|
81
|
+
else
|
82
|
+
|
83
|
+
return fe
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
paths = paths.map { |path| path.to_str }
|
64
88
|
|
65
89
|
return Recls::Ximpl.combine_paths paths, {}
|
66
90
|
end
|
@@ -4,11 +4,11 @@
|
|
4
4
|
# Purpose: Definition of Recls::compare_paths() for Ruby 2+
|
5
5
|
#
|
6
6
|
# Created: 17th February 2014
|
7
|
-
# Updated:
|
7
|
+
# Updated: 9th January 2025
|
8
8
|
#
|
9
9
|
# Author: Matthew Wilson
|
10
10
|
#
|
11
|
-
# Copyright (c) 2019-
|
11
|
+
# Copyright (c) 2019-2025, Matthew Wilson and Synesis Information Systems
|
12
12
|
# Copyright (c) 2014-2019, Matthew Wilson and Synesis Software
|
13
13
|
# All rights reserved.
|
14
14
|
#
|
@@ -45,7 +45,16 @@ require 'recls/ximpl/util'
|
|
45
45
|
|
46
46
|
module Recls
|
47
47
|
|
48
|
-
# Combines paths, optionally canonicalising them
|
48
|
+
# Combines paths, optionally canonicalising them.
|
49
|
+
#
|
50
|
+
# Unlike `File::join()`, this method takes account of relative vs absolute
|
51
|
+
# elements in the sequence. Specifically, the rightmost non-relative
|
52
|
+
# element, if it exists, anchors the combination, such that any arguments
|
53
|
+
# to the left are ignored. Furthermore, any entries (of type
|
54
|
+
# `Recls::Entry`) in the sequence are given special treatment as follows:
|
55
|
+
# - a rightmost `#file?` or `#device?` is returned as the complete result;
|
56
|
+
# - a rightmost `#directory?` causes all prior elements to be ignored and
|
57
|
+
# may be combined with subsequent elements;
|
49
58
|
#
|
50
59
|
# === Signature
|
51
60
|
#
|
@@ -66,7 +75,22 @@ module Recls
|
|
66
75
|
|
67
76
|
raise ArgumentError, 'must specify one or more path elements' if paths.empty?
|
68
77
|
|
69
|
-
ix_last_entry = paths.rindex { |path| ::Recls::Entry === path }
|
78
|
+
ix_last_entry = paths.rindex { |path| ::Recls::Entry === path }
|
79
|
+
|
80
|
+
if ix_last_entry
|
81
|
+
|
82
|
+
fe = paths[ix_last_entry]
|
83
|
+
|
84
|
+
if fe.directory?
|
85
|
+
|
86
|
+
paths = paths[ix_last_entry..]
|
87
|
+
else
|
88
|
+
|
89
|
+
return fe
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
paths = paths.map { |path| path.to_str }
|
70
94
|
|
71
95
|
return Recls::Ximpl.combine_paths paths, options
|
72
96
|
end
|
data/lib/recls/entry.rb
CHANGED
@@ -4,11 +4,11 @@
|
|
4
4
|
# Purpose: Defines the Recls::Entry class for the recls.Ruby library.
|
5
5
|
#
|
6
6
|
# Created: 24th July 2012
|
7
|
-
# Updated:
|
7
|
+
# Updated: 9th January 2025
|
8
8
|
#
|
9
9
|
# Author: Matthew Wilson
|
10
10
|
#
|
11
|
-
# Copyright (c) 2019-
|
11
|
+
# Copyright (c) 2019-2025, Matthew Wilson and Synesis Information Systems
|
12
12
|
# Copyright (c) 2012-2019, Matthew Wilson and Synesis Software
|
13
13
|
# All rights reserved.
|
14
14
|
#
|
@@ -64,6 +64,7 @@ module Recls
|
|
64
64
|
def initialize(path, file_stat, search_dir, flags)
|
65
65
|
|
66
66
|
@file_stat = file_stat
|
67
|
+
@flags = flags
|
67
68
|
|
68
69
|
@path = Recls::Ximpl.absolute_path path
|
69
70
|
@short_path = nil
|
@@ -104,6 +105,8 @@ module Recls
|
|
104
105
|
@short_path = @file_stat.short_path
|
105
106
|
@file_short_name = Recls::Ximpl::Util.split_path(@short_path)[2]
|
106
107
|
else
|
108
|
+
|
109
|
+
;
|
107
110
|
end
|
108
111
|
end
|
109
112
|
|
@@ -237,9 +240,13 @@ module Recls
|
|
237
240
|
# indicates whether the given entry represents a directory
|
238
241
|
def directory?
|
239
242
|
|
240
|
-
|
243
|
+
if @file_stat.nil?
|
241
244
|
|
242
|
-
|
245
|
+
(Recls::DETAILS_LATER | Recls::DIRECTORIES) == ((Recls::DETAILS_LATER | Recls::DIRECTORIES) & @flags)
|
246
|
+
else
|
247
|
+
|
248
|
+
@file_stat.directory?
|
249
|
+
end
|
243
250
|
end
|
244
251
|
|
245
252
|
alias_method :dir?, :directory?
|
@@ -247,9 +254,13 @@ module Recls
|
|
247
254
|
# indicates whether the given entry represents a file
|
248
255
|
def file?
|
249
256
|
|
250
|
-
|
257
|
+
if @file_stat.nil?
|
258
|
+
|
259
|
+
(Recls::DETAILS_LATER | Recls::FILES) == ((Recls::DETAILS_LATER | Recls::FILES) & @flags)
|
260
|
+
else
|
251
261
|
|
252
|
-
|
262
|
+
@file_stat.file?
|
263
|
+
end
|
253
264
|
end
|
254
265
|
|
255
266
|
# indicates whether the given entry represents a link
|
data/lib/recls/version.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Purpose: Version for recls library
|
5
5
|
#
|
6
6
|
# Created: 14th February 2014
|
7
|
-
# Updated:
|
7
|
+
# Updated: 24th April 2025
|
8
8
|
#
|
9
9
|
# Author: Matthew Wilson
|
10
10
|
#
|
@@ -43,7 +43,7 @@
|
|
43
43
|
module Recls
|
44
44
|
|
45
45
|
# Current version of the recls.Ruby library
|
46
|
-
VERSION = '2.13.
|
46
|
+
VERSION = '2.13.2'
|
47
47
|
|
48
48
|
private
|
49
49
|
# @!visibility private
|
data/lib/recls/ximpl/util.rb
CHANGED
@@ -780,7 +780,7 @@ module Recls
|
|
780
780
|
raise ArgumentError, "`paths` must be an instance of `::Array`" if $DEBUG && !paths.is_a?(::Array)
|
781
781
|
raise ArgumentError, "`paths` elements must be instances of `::String`" if $DEBUG && paths.any? { |s| !s.is_a?(::String) }
|
782
782
|
|
783
|
-
abs_ix
|
783
|
+
abs_ix = 0
|
784
784
|
|
785
785
|
paths = paths.map { |path| '~' == path[0].to_s ? File.expand_path(path) : path }
|
786
786
|
|
data/lib/recls/ximpl/windows.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Purpose: Windows-specific constructs for the recls library.
|
5
5
|
#
|
6
6
|
# Created: 19th February 2014
|
7
|
-
# Updated:
|
7
|
+
# Updated: 2nd June 2024
|
8
8
|
#
|
9
9
|
# Author: Matthew Wilson
|
10
10
|
#
|
@@ -37,7 +37,14 @@
|
|
37
37
|
# ######################################################################## #
|
38
38
|
|
39
39
|
|
40
|
-
|
40
|
+
if RUBY_VERSION >= '2'
|
41
|
+
|
42
|
+
require 'fiddle'
|
43
|
+
require 'fiddle/import'
|
44
|
+
else
|
45
|
+
|
46
|
+
require 'Win32API'
|
47
|
+
end
|
41
48
|
|
42
49
|
|
43
50
|
=begin
|
@@ -49,46 +56,136 @@ module Recls
|
|
49
56
|
module Ximpl # :nodoc: all
|
50
57
|
|
51
58
|
# @!visibility private
|
52
|
-
|
59
|
+
module Kernel32
|
60
|
+
|
61
|
+
MAX_PATH = 260
|
62
|
+
NULL = 0x00000000
|
63
|
+
OPEN_EXISTING = 0x00000003
|
64
|
+
end # module Kernel32
|
65
|
+
|
66
|
+
if RUBY_VERSION >= '2'
|
67
|
+
|
68
|
+
module Kernel32
|
69
|
+
extend Fiddle::Importer
|
70
|
+
|
71
|
+
dlload 'kernel32.dll'
|
72
|
+
|
73
|
+
typealias 'BOOL', 'int'
|
74
|
+
typealias 'DWORD', 'unsigned long'
|
75
|
+
typealias 'HANDLE', 'void*'
|
76
|
+
|
77
|
+
BY_HANDLE_FILE_INFORMATION = struct [
|
78
|
+
'DWORD dwFileAttributes',
|
79
|
+
'DWORD ftCreationTime_0',
|
80
|
+
'DWORD ftCreationTime_1',
|
81
|
+
'DWORD ftLastAccessTime_0',
|
82
|
+
'DWORD ftLastAccessTime_1',
|
83
|
+
'DWORD ftLastWriteTime_0',
|
84
|
+
'DWORD ftLastWriteTime_1',
|
85
|
+
'DWORD dwVolumeSerialNumber',
|
86
|
+
'DWORD nFileSizeHigh',
|
87
|
+
'DWORD nFileSizeLow',
|
88
|
+
'DWORD nNumberOfLinks',
|
89
|
+
'DWORD nFileIndexHigh',
|
90
|
+
'DWORD nFileIndexLow',
|
91
|
+
]
|
92
|
+
|
93
|
+
extern 'BOOL CloseHandle(HANDLE)'
|
94
|
+
extern 'HANDLE CreateFileA(const char*, DWORD, DWORD, void*, DWORD, DWORD, HANDLE)'
|
95
|
+
extern 'DWORD GetFileAttributesA(const char*)'
|
96
|
+
extern 'BOOL GetFileInformationByHandle(HANDLE, BY_HANDLE_FILE_INFORMATION*)'
|
97
|
+
extern 'DWORD GetShortPathNameA(const char*, char*, DWORD)'
|
98
|
+
|
99
|
+
INVALID_HANDLE_VALUE = Fiddle::Pointer[-1]
|
100
|
+
end # module Kernel32
|
101
|
+
|
102
|
+
module Kernel32
|
103
|
+
def self.get_file_attributes(path)
|
104
|
+
|
105
|
+
attributes = GetFileAttributesA(path)
|
106
|
+
|
107
|
+
(0xFFFFFFFF == attributes) ? 0 : attributes
|
108
|
+
end
|
53
109
|
|
54
|
-
|
55
|
-
GetFileAttributes = Win32API.new('kernel32', 'GetFileAttributes', [ 'P' ], 'I')
|
56
|
-
GetFileInformationByHandle = Win32API.new('kernel32', 'GetFileInformationByHandle', [ 'L', 'P' ], 'I')
|
57
|
-
GetShortPathName = Win32API.new('kernel32', 'GetShortPathName', [ 'P', 'P', 'L' ], 'L')
|
58
|
-
CreateFile = Win32API.new('kernel32', 'CreateFile', [ 'P', 'L', 'L', 'L', 'L', 'L', 'L' ], 'L')
|
59
|
-
CloseHandle = Win32API.new('kernel32', 'CloseHandle', [ 'L' ], 'L')
|
60
|
-
FILE_ATTRIBUTE_READONLY = 0x00000001
|
61
|
-
FILE_ATTRIBUTE_HIDDEN = 0x00000002
|
62
|
-
FILE_ATTRIBUTE_SYSTEM = 0x00000004
|
63
|
-
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
|
64
|
-
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
|
65
|
-
FILE_ATTRIBUTE_DEVICE = 0x00000040
|
66
|
-
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
67
|
-
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
|
68
|
-
FILE_ATTRIBUTE_COMPRESSED = 0x00000800
|
69
|
-
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
|
110
|
+
def self.get_short_path_name(path)
|
70
111
|
|
71
|
-
|
72
|
-
FILE_FLAG_OVERLAPPED = 0x40000000
|
73
|
-
NULL = 0x00000000
|
74
|
-
INVALID_HANDLE_VALUE = 0xFFFFFFFF
|
112
|
+
buff = ' ' * MAX_PATH
|
75
113
|
|
76
|
-
|
114
|
+
buf = Fiddle::Pointer[buff]
|
77
115
|
|
78
|
-
|
116
|
+
n = GetShortPathNameA(path, buf, buf.size)
|
79
117
|
|
80
|
-
|
81
|
-
|
118
|
+
(0 == n) ? nil : buff[0...n]
|
119
|
+
end
|
82
120
|
|
83
|
-
|
84
|
-
|
121
|
+
def self.get_stat_shared(path)
|
122
|
+
|
123
|
+
volume_id = 0
|
124
|
+
file_index = 0
|
125
|
+
num_links = 0
|
85
126
|
|
86
|
-
|
87
|
-
|
88
|
-
|
127
|
+
hFile = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL)
|
128
|
+
|
129
|
+
if INVALID_HANDLE_VALUE != hFile
|
130
|
+
|
131
|
+
begin
|
132
|
+
bhfi = BY_HANDLE_FILE_INFORMATION.malloc
|
133
|
+
|
134
|
+
if GetFileInformationByHandle(hFile, bhfi)
|
135
|
+
|
136
|
+
volume_id = bhfi.dwVolumeSerialNumber
|
137
|
+
file_index = (bhfi.nFileIndexHigh << 32) | bhfi.nFileIndexLow
|
138
|
+
num_links = bhfi.nNumberOfLinks
|
139
|
+
end
|
140
|
+
ensure
|
141
|
+
|
142
|
+
CloseHandle(hFile)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
[ volume_id, file_index, num_links ]
|
147
|
+
end
|
148
|
+
end # module Kernel32
|
149
|
+
else
|
150
|
+
|
151
|
+
module Kernel32
|
152
|
+
|
153
|
+
CloseHandle = Win32API.new('kernel32', 'CloseHandle', [ 'L' ], 'L')
|
154
|
+
CreateFile = Win32API.new('kernel32', 'CreateFile', [ 'P', 'L', 'L', 'L', 'L', 'L', 'L' ], 'L')
|
155
|
+
GetFileAttributes = Win32API.new('kernel32', 'GetFileAttributes', [ 'P' ], 'I')
|
156
|
+
GetFileInformationByHandle = Win32API.new('kernel32', 'GetFileInformationByHandle', [ 'L', 'P' ], 'I')
|
157
|
+
GetShortPathName = Win32API.new('kernel32', 'GetShortPathName', [ 'P', 'P', 'L' ], 'L')
|
158
|
+
|
159
|
+
INVALID_HANDLE_VALUE = -1
|
160
|
+
|
161
|
+
BHFI_pack_string = 'LQQQLLLLLL'
|
162
|
+
end # module Kernel32
|
163
|
+
|
164
|
+
module Kernel32
|
165
|
+
def self.get_file_attributes(path)
|
166
|
+
|
167
|
+
attributes = GetFileAttributes.call(path)
|
168
|
+
|
169
|
+
(0xFFFFFFFF == attributes) ? 0 : attributes
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.get_short_path_name(path)
|
173
|
+
|
174
|
+
buff = ' ' * MAX_PATH
|
175
|
+
|
176
|
+
n = GetShortPathName.call(path, buff, buff.length)
|
177
|
+
|
178
|
+
(0 == n) ? nil : buff[0...n]
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.get_stat_shared(path)
|
182
|
+
|
183
|
+
volume_id = 0
|
184
|
+
file_index = 0
|
185
|
+
num_links = 0
|
186
|
+
|
187
|
+
hFile = CreateFile.call(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL)
|
89
188
|
|
90
|
-
# for some reason not forcing this new string causes 'can't modify frozen string (TypeError)' (in Ruby 1.8.x)
|
91
|
-
hFile = CreateFile.call("#{path}", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
|
92
189
|
if INVALID_HANDLE_VALUE != hFile
|
93
190
|
|
94
191
|
begin
|
@@ -99,15 +196,43 @@ module Recls
|
|
99
196
|
|
100
197
|
bhfi = bhfi.unpack(BHFI_pack_string)
|
101
198
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
else
|
199
|
+
volume_id = bhfi[4]
|
200
|
+
file_index = (bhfi[8] << 32) | bhfi[9]
|
201
|
+
num_links = bhfi[7]
|
106
202
|
end
|
107
203
|
ensure
|
204
|
+
|
108
205
|
CloseHandle.call(hFile)
|
109
206
|
end
|
110
207
|
end
|
208
|
+
|
209
|
+
[ volume_id, file_index, num_links ]
|
210
|
+
end
|
211
|
+
end # module Kernel32
|
212
|
+
end
|
213
|
+
|
214
|
+
# @!visibility private
|
215
|
+
class FileStat < File::Stat # :nodoc:
|
216
|
+
|
217
|
+
private
|
218
|
+
FILE_ATTRIBUTE_READONLY = 0x00000001
|
219
|
+
FILE_ATTRIBUTE_HIDDEN = 0x00000002
|
220
|
+
FILE_ATTRIBUTE_SYSTEM = 0x00000004
|
221
|
+
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
|
222
|
+
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
|
223
|
+
FILE_ATTRIBUTE_DEVICE = 0x00000040
|
224
|
+
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
225
|
+
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
|
226
|
+
FILE_ATTRIBUTE_COMPRESSED = 0x00000800
|
227
|
+
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
|
228
|
+
|
229
|
+
# @!visibility private
|
230
|
+
class ByHandleInformation # :nodoc:
|
231
|
+
|
232
|
+
# @!visibility private
|
233
|
+
def initialize(path) # :nodoc:
|
234
|
+
|
235
|
+
@volume_id, @file_index, @num_links = Kernel32.get_stat_shared(path)
|
111
236
|
end
|
112
237
|
|
113
238
|
# @!visibility private
|
@@ -129,27 +254,18 @@ module Recls
|
|
129
254
|
# @!visibility private
|
130
255
|
def initialize(path) # :nodoc:
|
131
256
|
|
132
|
-
|
133
|
-
|
134
|
-
# for some reason not forcing this new string causes 'can't modify frozen string (TypeError)'
|
135
|
-
attributes = GetFileAttributes.call("#{path}")
|
257
|
+
path = path.to_str
|
136
258
|
|
137
|
-
|
259
|
+
@path = path
|
138
260
|
|
139
|
-
|
140
|
-
else
|
141
|
-
|
142
|
-
@attributes = attributes
|
143
|
-
end
|
261
|
+
@attributes = Kernel32.get_file_attributes(path)
|
144
262
|
|
145
263
|
super(path)
|
146
264
|
|
147
265
|
@by_handle_information = ByHandleInformation.new(path)
|
148
266
|
|
149
|
-
|
150
|
-
|
151
|
-
n = GetShortPathName.call("#{path}", buff, buff.length)
|
152
|
-
@short_path = (0 == n) ? nil : buff[0...n]
|
267
|
+
@short_path = Kernel32.get_short_path_name(path)
|
268
|
+
|
153
269
|
end
|
154
270
|
|
155
271
|
public
|
@@ -165,7 +281,7 @@ module Recls
|
|
165
281
|
# @!visibility private
|
166
282
|
def hidden? # :nodoc:
|
167
283
|
|
168
|
-
|
284
|
+
has_attribute_? FILE_ATTRIBUTE_HIDDEN
|
169
285
|
end
|
170
286
|
|
171
287
|
# Windows-specific attributes
|
@@ -215,7 +331,7 @@ module Recls
|
|
215
331
|
|
216
332
|
public
|
217
333
|
# @!visibility private
|
218
|
-
def
|
334
|
+
def self.stat(path) # :nodoc:
|
219
335
|
|
220
336
|
Recls::Ximpl::FileStat.new(path)
|
221
337
|
end
|
data/test/unit/tc_recls_entry.rb
CHANGED
@@ -19,7 +19,7 @@ class Test_Recls_entry < Test::Unit::TestCase
|
|
19
19
|
|
20
20
|
def setup
|
21
21
|
|
22
|
-
@cwd = Dir.pwd
|
22
|
+
@cwd = Dir.pwd.freeze
|
23
23
|
end
|
24
24
|
|
25
25
|
def test_entry_does_not_mark_directory
|
@@ -51,5 +51,22 @@ class Test_Recls_entry < Test::Unit::TestCase
|
|
51
51
|
|
52
52
|
assert_not_equal cwd.object_id, cwd2.object_id
|
53
53
|
end
|
54
|
+
|
55
|
+
if Recls.windows?
|
56
|
+
|
57
|
+
def test_entry_file_short_name
|
58
|
+
|
59
|
+
cwd = Recls.stat @cwd
|
60
|
+
|
61
|
+
if cwd.file_short_name
|
62
|
+
|
63
|
+
if cwd.file_full_name != cwd.file_short_name
|
64
|
+
|
65
|
+
assert cwd.file_short_name =~ /^.{0,8}\..{0,3}$/, "'#{cwd.file_short_name}' does not match expected 8.3 form"
|
66
|
+
assert_equal cwd.file_short_name.upcase, cwd.file_short_name, "'#{cwd.file_short_name}' is not uppercase as expected"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
54
71
|
end
|
55
72
|
|
data/test/unit/tc_recls_util.rb
CHANGED
@@ -13,115 +13,6 @@ end
|
|
13
13
|
require 'test/unit'
|
14
14
|
|
15
15
|
|
16
|
-
class Test_combine_paths < Test::Unit::TestCase
|
17
|
-
|
18
|
-
def test_nil_nil
|
19
|
-
|
20
|
-
if RUBY_VERSION >= '2'
|
21
|
-
|
22
|
-
assert_raise_with_message(::ArgumentError, /must specify one or more path elements/) { Recls.combine_paths(nil, nil) }
|
23
|
-
else
|
24
|
-
|
25
|
-
assert_raise(::ArgumentError) { Recls.combine_paths(nil, nil) }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_origin_nil
|
30
|
-
|
31
|
-
strings = [
|
32
|
-
|
33
|
-
'abc',
|
34
|
-
'abc/def',
|
35
|
-
'abc/def/ghi.ext',
|
36
|
-
]
|
37
|
-
|
38
|
-
strings.each do |s|
|
39
|
-
|
40
|
-
assert_equal s, Recls.combine_paths(nil, s)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_path_nil
|
45
|
-
|
46
|
-
strings = [
|
47
|
-
|
48
|
-
'abc',
|
49
|
-
'abc/def',
|
50
|
-
'abc/def/ghi.ext',
|
51
|
-
]
|
52
|
-
|
53
|
-
strings.each do |s|
|
54
|
-
|
55
|
-
assert_equal s, Recls.combine_paths(s, nil)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_both_relative
|
60
|
-
|
61
|
-
assert_equal 'abc/def', Recls.combine_paths('abc', 'def')
|
62
|
-
assert_equal 'abc/def', Recls.combine_paths('abc/', 'def')
|
63
|
-
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/def', 'ghi')
|
64
|
-
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/def/', 'ghi')
|
65
|
-
assert_equal 'abc/def/ghi', Recls.combine_paths('abc', 'def/ghi')
|
66
|
-
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/', 'def/ghi')
|
67
|
-
assert_equal 'abc/./def/ghi', Recls.combine_paths('abc/.', 'def/ghi')
|
68
|
-
assert_equal 'abc/./def/ghi', Recls.combine_paths('abc/./', 'def/ghi')
|
69
|
-
|
70
|
-
if RUBY_VERSION >= '2'
|
71
|
-
|
72
|
-
assert_equal 'abc/./def/ghi', Recls.combine_paths('abc/.', 'def/ghi', clean_path: false)
|
73
|
-
assert_equal 'abc/./def/ghi', Recls.combine_paths('abc/./', 'def/ghi', clean: false)
|
74
|
-
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/.', 'def/ghi', clean_path: true)
|
75
|
-
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/./', 'def/ghi', clean: true)
|
76
|
-
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/./.', 'def/ghi', clean_path: true)
|
77
|
-
assert_equal 'abc/../def/ghi', Recls.combine_paths('abc/..', 'def/ghi')
|
78
|
-
assert_equal 'def/ghi', Recls.combine_paths('abc/..', 'def/ghi', clean_path: true)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_multiple_relative
|
83
|
-
|
84
|
-
if RUBY_VERSION >= '2'
|
85
|
-
|
86
|
-
assert_equal 'a/b/c/d/e/f/g', Recls.combine_paths('a', 'b', 'c', 'd/e/f/', 'g', clean: false)
|
87
|
-
assert_equal 'a/b/c/d/e/f/g', Recls.combine_paths('a', 'b', 'c', 'd/e/f/', 'g', clean: true)
|
88
|
-
|
89
|
-
assert_equal 'a/b/c/../d/e/f/g', Recls.combine_paths('a', 'b', 'c', '..', 'd/e/f/', 'g', clean: false)
|
90
|
-
assert_equal 'a/b/d/e/f/g', Recls.combine_paths('a', 'b', 'c', '..', 'd/e/f/', 'g/', clean: true)
|
91
|
-
assert_equal 'a/b/d/e/f/g/', Recls.combine_paths('a', 'b', 'c', '..', 'd/e/f/', 'g/', canonicalise: true)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def test_various_absolute_placings
|
96
|
-
|
97
|
-
assert_equal '/a/b/c/d/e/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', 'f/g')
|
98
|
-
|
99
|
-
assert_equal '/b/c/d/e/f/g', Recls.combine_paths('/', 'a', '/b', 'c', 'd/e', 'f/g')
|
100
|
-
|
101
|
-
assert_equal '/c/d/e/f/g', Recls.combine_paths('/', 'a', 'b', '/c', 'd/e', 'f/g')
|
102
|
-
|
103
|
-
assert_equal '/d/e/f/g', Recls.combine_paths('/', 'a', 'b', 'c', '/d/e', 'f/g')
|
104
|
-
|
105
|
-
assert_equal '/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g')
|
106
|
-
assert_equal '/f/g/', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g/')
|
107
|
-
|
108
|
-
if RUBY_VERSION >= '2'
|
109
|
-
|
110
|
-
assert_equal '/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g/', clean: true)
|
111
|
-
assert_equal '/f/g/', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g/', canonicalise: true)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def test_combining_with_entries
|
116
|
-
|
117
|
-
f_g = Recls.stat('/f/g', Recls::DETAILS_LATER)
|
118
|
-
b = Recls.stat('b', Recls::DETAILS_LATER)
|
119
|
-
|
120
|
-
assert_equal '/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', f_g)
|
121
|
-
assert_equal '/f/g', Recls.combine_paths('/', 'a', b, 'c', 'd/e', f_g)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
16
|
class Test_canonicalise_path < Test::Unit::TestCase
|
126
17
|
|
127
18
|
def test_nil
|
@@ -0,0 +1,158 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), '../../..', 'lib')
|
4
|
+
|
5
|
+
require 'recls'
|
6
|
+
|
7
|
+
require 'xqsr3/extensions/test/unit'
|
8
|
+
require 'test/unit'
|
9
|
+
|
10
|
+
require 'fileutils'
|
11
|
+
|
12
|
+
|
13
|
+
class Test_combine_paths < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def test_nil_nil
|
16
|
+
|
17
|
+
if RUBY_VERSION >= '2'
|
18
|
+
|
19
|
+
assert_raise_with_message(::ArgumentError, /must specify one or more path elements/) { Recls.combine_paths(nil, nil) }
|
20
|
+
else
|
21
|
+
|
22
|
+
assert_raise(::ArgumentError) { Recls.combine_paths(nil, nil) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_origin_nil
|
27
|
+
|
28
|
+
strings = [
|
29
|
+
|
30
|
+
'abc',
|
31
|
+
'abc/def',
|
32
|
+
'abc/def/ghi.ext',
|
33
|
+
]
|
34
|
+
|
35
|
+
strings.each do |s|
|
36
|
+
|
37
|
+
assert_equal s, Recls.combine_paths(nil, s)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_path_nil
|
42
|
+
|
43
|
+
strings = [
|
44
|
+
|
45
|
+
'abc',
|
46
|
+
'abc/def',
|
47
|
+
'abc/def/ghi.ext',
|
48
|
+
]
|
49
|
+
|
50
|
+
strings.each do |s|
|
51
|
+
|
52
|
+
assert_equal s, Recls.combine_paths(s, nil)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_both_relative
|
57
|
+
|
58
|
+
assert_equal 'abc/def', Recls.combine_paths('abc', 'def')
|
59
|
+
assert_equal 'abc/def', Recls.combine_paths('abc/', 'def')
|
60
|
+
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/def', 'ghi')
|
61
|
+
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/def/', 'ghi')
|
62
|
+
assert_equal 'abc/def/ghi', Recls.combine_paths('abc', 'def/ghi')
|
63
|
+
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/', 'def/ghi')
|
64
|
+
assert_equal 'abc/./def/ghi', Recls.combine_paths('abc/.', 'def/ghi')
|
65
|
+
assert_equal 'abc/./def/ghi', Recls.combine_paths('abc/./', 'def/ghi')
|
66
|
+
|
67
|
+
if RUBY_VERSION >= '2'
|
68
|
+
|
69
|
+
assert_equal 'abc/./def/ghi', Recls.combine_paths('abc/.', 'def/ghi', clean_path: false)
|
70
|
+
assert_equal 'abc/./def/ghi', Recls.combine_paths('abc/./', 'def/ghi', clean: false)
|
71
|
+
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/.', 'def/ghi', clean_path: true)
|
72
|
+
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/./', 'def/ghi', clean: true)
|
73
|
+
assert_equal 'abc/def/ghi', Recls.combine_paths('abc/./.', 'def/ghi', clean_path: true)
|
74
|
+
assert_equal 'abc/../def/ghi', Recls.combine_paths('abc/..', 'def/ghi')
|
75
|
+
assert_equal 'def/ghi', Recls.combine_paths('abc/..', 'def/ghi', clean_path: true)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_multiple_relative
|
80
|
+
|
81
|
+
if RUBY_VERSION >= '2'
|
82
|
+
|
83
|
+
assert_equal 'a/b/c/d/e/f/g', Recls.combine_paths('a', 'b', 'c', 'd/e/f/', 'g', clean: false)
|
84
|
+
assert_equal 'a/b/c/d/e/f/g', Recls.combine_paths('a', 'b', 'c', 'd/e/f/', 'g', clean: true)
|
85
|
+
|
86
|
+
assert_equal 'a/b/c/../d/e/f/g', Recls.combine_paths('a', 'b', 'c', '..', 'd/e/f/', 'g', clean: false)
|
87
|
+
assert_equal 'a/b/d/e/f/g', Recls.combine_paths('a', 'b', 'c', '..', 'd/e/f/', 'g/', clean: true)
|
88
|
+
assert_equal 'a/b/d/e/f/g/', Recls.combine_paths('a', 'b', 'c', '..', 'd/e/f/', 'g/', canonicalise: true)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_various_absolute_placings
|
93
|
+
|
94
|
+
assert_equal '/a/b/c/d/e/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', 'f/g')
|
95
|
+
|
96
|
+
assert_equal '/b/c/d/e/f/g', Recls.combine_paths('/', 'a', '/b', 'c', 'd/e', 'f/g')
|
97
|
+
|
98
|
+
assert_equal '/c/d/e/f/g', Recls.combine_paths('/', 'a', 'b', '/c', 'd/e', 'f/g')
|
99
|
+
|
100
|
+
assert_equal '/d/e/f/g', Recls.combine_paths('/', 'a', 'b', 'c', '/d/e', 'f/g')
|
101
|
+
|
102
|
+
assert_equal '/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g')
|
103
|
+
assert_equal '/f/g/', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g/')
|
104
|
+
|
105
|
+
if RUBY_VERSION >= '2'
|
106
|
+
|
107
|
+
assert_equal '/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g/', clean: true)
|
108
|
+
assert_equal '/f/g/', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g/', canonicalise: true)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_combining_with_entries
|
113
|
+
|
114
|
+
f_g = Recls.stat('/f/g', Recls::DETAILS_LATER | Recls::DIRECTORIES)
|
115
|
+
b = Recls.stat('b', Recls::DETAILS_LATER | Recls::DIRECTORIES)
|
116
|
+
root_b = Recls.stat('/b', Recls::DETAILS_LATER | Recls::DIRECTORIES)
|
117
|
+
|
118
|
+
assert_equal '/a/b/c/d/e/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', 'f/g')
|
119
|
+
assert_equal '/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', '/f/g')
|
120
|
+
|
121
|
+
assert_equal '/f/g', Recls.combine_paths('/', 'a', 'b', 'c', 'd/e', f_g)
|
122
|
+
assert_equal '/f/g', Recls.combine_paths('/', 'a', b, 'c', 'd/e', f_g)
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_combining_with_entries_that_exist
|
126
|
+
|
127
|
+
fe_this_file = Recls.stat(__FILE__)
|
128
|
+
fe_this_dir = Recls.stat(File.dirname(__FILE__))
|
129
|
+
|
130
|
+
assert_true fe_this_file.file?
|
131
|
+
assert_false fe_this_file.directory?
|
132
|
+
|
133
|
+
assert_true fe_this_dir.directory?
|
134
|
+
assert_false fe_this_dir.file?
|
135
|
+
|
136
|
+
assert_equal fe_this_file.to_s, Recls.combine_paths(fe_this_file)
|
137
|
+
assert_equal fe_this_file.to_s, Recls.combine_paths(nil, fe_this_file)
|
138
|
+
assert_equal fe_this_file.to_s, Recls.combine_paths('abc', fe_this_file)
|
139
|
+
assert_equal fe_this_file.to_s, Recls.combine_paths(fe_this_file)
|
140
|
+
assert_equal fe_this_file.to_s, Recls.combine_paths(fe_this_file, nil)
|
141
|
+
assert_equal fe_this_file.to_s, Recls.combine_paths(fe_this_file, '')
|
142
|
+
assert_equal fe_this_file.to_s, Recls.combine_paths(fe_this_file, 'abc')
|
143
|
+
assert_equal fe_this_file.to_s, Recls.combine_paths('abc', fe_this_file, 'abc')
|
144
|
+
|
145
|
+
assert_equal fe_this_dir.to_s, Recls.combine_paths(fe_this_dir)
|
146
|
+
assert_equal fe_this_dir.to_s, Recls.combine_paths(nil, fe_this_dir)
|
147
|
+
assert_equal fe_this_dir.to_s, Recls.combine_paths('abc', fe_this_dir)
|
148
|
+
assert_equal fe_this_dir.to_s, Recls.combine_paths(fe_this_dir)
|
149
|
+
assert_equal fe_this_dir.to_s, Recls.combine_paths(fe_this_dir, nil)
|
150
|
+
assert_equal "#{fe_this_dir.to_s}/", Recls.combine_paths(fe_this_dir, '')
|
151
|
+
assert_equal "#{fe_this_dir.to_s}/abc", Recls.combine_paths(fe_this_dir, 'abc')
|
152
|
+
assert_equal "#{fe_this_dir.to_s}/abc", Recls.combine_paths('abc', fe_this_dir, 'abc')
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
# ############################## end of file ############################# #
|
158
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# executes all other tests
|
4
|
+
|
5
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
6
|
+
|
7
|
+
# all tc_*rb in current directory
|
8
|
+
Dir[File.join(this_dir, 'tc_*rb')].each do |file|
|
9
|
+
|
10
|
+
$stderr.puts "requiring file '#{file}'" if $DEBUG
|
11
|
+
|
12
|
+
require file
|
13
|
+
end
|
14
|
+
|
15
|
+
# all ts_*rb in immediate sub-directories
|
16
|
+
Dir[File.join(this_dir, '*', 'ts_*rb')].each do |file|
|
17
|
+
|
18
|
+
$stderr.puts "requiring file '#{file}'" if $DEBUG
|
19
|
+
|
20
|
+
require file
|
21
|
+
end
|
22
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: recls-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.13.
|
4
|
+
version: 2.13.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Wilson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xqsr3
|
@@ -79,6 +79,8 @@ files:
|
|
79
79
|
- test/unit/test_all_separately.cmd
|
80
80
|
- test/unit/test_all_separately.sh
|
81
81
|
- test/unit/ts_all.rb
|
82
|
+
- test/unit/util/tc_combine_paths.rb
|
83
|
+
- test/unit/util/ts_all.rb
|
82
84
|
homepage: http://github.com/synesissoftware/recls.Ruby
|
83
85
|
licenses:
|
84
86
|
- BSD-3-Clause
|
@@ -98,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
100
|
- !ruby/object:Gem::Version
|
99
101
|
version: '0'
|
100
102
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
103
|
+
rubygems_version: 3.1.6
|
102
104
|
signing_key:
|
103
105
|
specification_version: 4
|
104
106
|
summary: recls.Ruby
|