recls-ruby 2.12.0 → 2.12.0.1

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +27 -24
  3. data/README.md +242 -1
  4. data/examples/find_files_and_directories.md +33 -30
  5. data/examples/find_files_and_directories.recursive.md +255 -254
  6. data/examples/show_hidden_files.md +4 -1
  7. data/examples/show_hidden_files.rb +1 -1
  8. data/examples/show_readonly_files.md +4 -1
  9. data/examples/show_readonly_files.rb +1 -1
  10. data/lib/recls/api.rb +76 -73
  11. data/lib/recls/combine_paths_1.rb +26 -23
  12. data/lib/recls/combine_paths_2plus.rb +32 -29
  13. data/lib/recls/entry.rb +277 -273
  14. data/lib/recls/file_search.rb +194 -193
  15. data/lib/recls/flags.rb +48 -45
  16. data/lib/recls/foreach.rb +105 -98
  17. data/lib/recls/obsolete.rb +85 -79
  18. data/lib/recls/recls.rb +19 -24
  19. data/lib/recls/stat.rb +137 -134
  20. data/lib/recls/util.rb +95 -92
  21. data/lib/recls/version.rb +22 -17
  22. data/lib/recls/ximpl/os.rb +49 -48
  23. data/lib/recls/ximpl/unix.rb +41 -38
  24. data/lib/recls/ximpl/util.rb +600 -599
  25. data/lib/recls/ximpl/windows.rb +142 -139
  26. data/lib/recls.rb +10 -9
  27. data/test/scratch/test_display_parts.rb +33 -33
  28. data/test/scratch/test_entry.rb +6 -6
  29. data/test/scratch/test_files_and_directories.rb +8 -8
  30. data/test/scratch/test_foreach.rb +10 -10
  31. data/test/scratch/test_module_function.rb +33 -33
  32. data/test/scratch/test_pattern_arrays.rb +5 -5
  33. data/test/scratch/test_show_dev_and_ino.rb +1 -1
  34. data/test/scratch/test_show_hidden.rb +3 -3
  35. data/test/unit/tc_recls_entries.rb +31 -31
  36. data/test/unit/tc_recls_entry.rb +19 -19
  37. data/test/unit/tc_recls_file_search.rb +32 -32
  38. data/test/unit/tc_recls_module.rb +25 -25
  39. data/test/unit/tc_recls_util.rb +161 -161
  40. data/test/unit/tc_recls_ximpl_util.rb +676 -676
  41. data/test/unit/test_all_separately.sh +1 -1
  42. data/test/unit/ts_all.rb +4 -4
  43. metadata +7 -7
@@ -1,13 +1,14 @@
1
- # ######################################################################### #
2
- # File: recls/ximpl/util.rb
1
+ # ######################################################################## #
2
+ # File: recls/ximpl/util.rb
3
3
  #
4
- # Purpose: Internal implementation constructs for the recls library.
4
+ # Purpose: Internal implementation constructs for the recls library.
5
5
  #
6
- # Created: 24th July 2012
7
- # Updated: 14th April 2019
6
+ # Created: 24th July 2012
7
+ # Updated: 20th April 2024
8
8
  #
9
- # Author: Matthew Wilson
9
+ # Author: Matthew Wilson
10
10
  #
11
+ # Copyright (c) 2019-2024, Matthew Wilson and Synesis Information Systems
11
12
  # Copyright (c) 2012-2019, Matthew Wilson and Synesis Software
12
13
  # All rights reserved.
13
14
  #
@@ -33,7 +34,7 @@
33
34
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
35
  # POSSIBILITY OF SUCH DAMAGE.
35
36
  #
36
- # ######################################################################### #
37
+ # ######################################################################## #
37
38
 
38
39
 
39
40
  require 'recls/ximpl/os'
@@ -41,839 +42,839 @@ require 'recls/flags'
41
42
 
42
43
  require 'pathname'
43
44
 
45
+
44
46
  =begin
45
47
  =end
46
48
 
47
- module Recls # :nodoc:
48
-
49
49
  # :stopdoc:
50
50
 
51
- module Ximpl # :nodoc: all
51
+ module Recls # :nodoc:
52
+
53
+ # @!visibility private
54
+ module Ximpl # :nodoc: all
52
55
 
53
- module Util # :nodoc: all
56
+ module Util # :nodoc: all
54
57
 
55
- # @!visibility private
56
- def self.is_path_name_separator(c) # :nodoc:
58
+ # @!visibility private
59
+ def self.is_path_name_separator(c) # :nodoc:
57
60
 
58
- return true if ?/ == c
61
+ return true if ?/ == c
59
62
 
60
- if Recls::Ximpl::OS::OS_IS_WINDOWS
63
+ if Recls::Ximpl::OS::OS_IS_WINDOWS
61
64
 
62
- return true if ?\\ == c
63
- end
65
+ return true if ?\\ == c
66
+ end
64
67
 
65
- return false
66
- end
68
+ return false
69
+ end
67
70
 
68
- # Indicates whether a trailing slash is on the given path
69
- #
70
- # dependencies: none
71
- #
72
- # @!visibility private
73
- def self.has_trailing_slash(p) # :nodoc:
71
+ # Indicates whether a trailing slash is on the given path
72
+ #
73
+ # dependencies: none
74
+ #
75
+ # @!visibility private
76
+ def self.has_trailing_slash(p) # :nodoc:
74
77
 
75
- return p if p.nil? or p.empty?
78
+ return p if p.nil? or p.empty?
76
79
 
77
- return self.is_path_name_separator(p[-1])
78
- end
80
+ return self.is_path_name_separator(p[-1])
81
+ end
79
82
 
80
- # returns the trailing slash, or nil if none present
81
- #
82
- # dependencies: none
83
- #
84
- # @!visibility private
85
- def self.get_trailing_slash(p, args = {}) # :nodoc:
83
+ # returns the trailing slash, or nil if none present
84
+ #
85
+ # dependencies: none
86
+ #
87
+ # @!visibility private
88
+ def self.get_trailing_slash(p, args = {}) # :nodoc:
86
89
 
87
- return nil if p.nil?
88
- return nil if p.empty?
90
+ return nil if p.nil?
91
+ return nil if p.empty?
89
92
 
90
- return self.is_path_name_separator(p[-1]) ? p[-1] : nil
91
- end
93
+ return self.is_path_name_separator(p[-1]) ? p[-1] : nil
94
+ end
92
95
 
93
- # appends trailing slash to a path if not already
94
- # present
95
- #
96
- # dependencies: none
97
- #
98
- # @!visibility private
99
- def self.append_trailing_slash(p, slash = nil) # :nodoc:
96
+ # appends trailing slash to a path if not already
97
+ # present
98
+ #
99
+ # dependencies: none
100
+ #
101
+ # @!visibility private
102
+ def self.append_trailing_slash(p, slash = nil) # :nodoc:
100
103
 
101
- return p if not p or p.empty?
104
+ return p if not p or p.empty?
102
105
 
103
- return p if self.is_path_name_separator(p[-1])
106
+ return p if self.is_path_name_separator(p[-1])
104
107
 
105
- slash = '/' if not slash
108
+ slash = '/' if not slash
106
109
 
107
- "#{p}#{slash}"
108
- end
110
+ "#{p}#{slash}"
111
+ end
109
112
 
110
- # trims trailing slash from a path, unless it is the
111
- # root
112
- #
113
- # dependencies: none
114
- #
115
- # @!visibility private
116
- def self.trim_trailing_slash(p) # :nodoc:
113
+ # trims trailing slash from a path, unless it is the
114
+ # root
115
+ #
116
+ # dependencies: none
117
+ #
118
+ # @!visibility private
119
+ def self.trim_trailing_slash(p) # :nodoc:
117
120
 
118
- return p if not p or p.empty?
121
+ return p if not p or p.empty?
119
122
 
120
- p = p[0 ... -1] if self.is_path_name_separator(p[-1])
123
+ p = p[0 ... -1] if self.is_path_name_separator(p[-1])
121
124
 
122
- return p
123
- end
125
+ return p
126
+ end
124
127
 
125
- # From path p, returns a tuple containing either:
126
- #
127
- # [ nil, p ] if p does not contain a Windows root, or
128
- #
129
- # [ wroot, remainder ] if p does contain a Windows root, or
130
- #
131
- # [ nil, nil ] if p is nil
132
- #
133
- # dependencies: none
134
- #
135
- # @!visibility private
136
- def self.get_windows_root(p) # :nodoc:
128
+ # From path p, returns a tuple containing either:
129
+ #
130
+ # [ nil, p ] if p does not contain a Windows root, or
131
+ #
132
+ # [ wroot, remainder ] if p does contain a Windows root, or
133
+ #
134
+ # [ nil, nil ] if p is nil
135
+ #
136
+ # dependencies: none
137
+ #
138
+ # @!visibility private
139
+ def self.get_windows_root(p) # :nodoc:
137
140
 
138
- return [ nil, nil ] if not p
141
+ return [ nil, nil ] if not p
139
142
 
140
- if Recls::Ximpl::OS::OS_IS_WINDOWS
143
+ if Recls::Ximpl::OS::OS_IS_WINDOWS
141
144
 
142
- # Windows local drive (e.g. 'H:')
143
- #
144
- # NOTE: this works for both rooted and unrooted paths
145
- if p =~ /^([a-zA-Z]:)/
145
+ # Windows local drive (e.g. 'H:')
146
+ #
147
+ # NOTE: this works for both rooted and unrooted paths
148
+ if p =~ /^([a-zA-Z]:)/
146
149
 
147
- return [ $1, $' ]
148
- end
150
+ return [ $1, $' ]
151
+ end
149
152
 
150
- # UNC network drive
151
- #
152
- # NOTE: there are several permutations ...
153
- if p =~ /^(\\\\[^\\\/:*?<>|]+\\[^\\\/:*?<>|]+)([\\\/].*)$/
153
+ # UNC network drive
154
+ #
155
+ # NOTE: there are several permutations ...
156
+ if p =~ /^(\\\\[^\\\/:*?<>|]+\\[^\\\/:*?<>|]+)([\\\/].*)$/
154
157
 
155
- # \\server\share{\{... rest of path}}
156
- return [ $1, $2 ]
157
- end
158
- if p =~ /^(\\\\[^\\\/:*?<>|]+\\[^\\\/:*?<>|]+)$/
158
+ # \\server\share{\{... rest of path}}
159
+ return [ $1, $2 ]
160
+ end
161
+ if p =~ /^(\\\\[^\\\/:*?<>|]+\\[^\\\/:*?<>|]+)$/
159
162
 
160
- # \\server\share
161
- return [ $1, nil ]
162
- end
163
- if p =~ /^(\\\\[^\\\/:*?<>|]+\\)$/
164
-
165
- # \\server\
166
- return [ $1, nil ]
167
- end
168
- if p =~ /^(\\\\[^\\\/:*?<>|]+)$/
169
-
170
- # \\server
171
- return [ $1, nil ]
172
- end
173
- end
174
-
175
- return [ nil, p ]
176
- end
177
-
178
- # obtains the parts from a path, including any Windows root and
179
- # the file basename
180
- #
181
- # @!visibility private
182
- def self.path_parts(path) # :nodoc:
183
-
184
- return nil if path.nil?
185
- return [] if path.empty?
186
-
187
- parts = []
188
-
189
- wr, rem = self.get_windows_root(path)
190
-
191
- parts << wr if wr
192
-
193
- until rem.nil? || rem.empty?
194
-
195
- if rem =~ /^([^\\\/]*[\\\/])/
196
-
197
- parts << $1
198
- rem = $'
199
- else
163
+ # \\server\share
164
+ return [ $1, nil ]
165
+ end
166
+ if p =~ /^(\\\\[^\\\/:*?<>|]+\\)$/
167
+
168
+ # \\server\
169
+ return [ $1, nil ]
170
+ end
171
+ if p =~ /^(\\\\[^\\\/:*?<>|]+)$/
172
+
173
+ # \\server
174
+ return [ $1, nil ]
175
+ end
176
+ end
177
+
178
+ return [ nil, p ]
179
+ end
180
+
181
+ # obtains the parts from a path, including any Windows root and
182
+ # the file basename
183
+ #
184
+ # @!visibility private
185
+ def self.path_parts(path) # :nodoc:
186
+
187
+ return nil if path.nil?
188
+ return [] if path.empty?
189
+
190
+ parts = []
191
+
192
+ wr, rem = self.get_windows_root(path)
193
+
194
+ parts << wr if wr
195
+
196
+ until rem.nil? || rem.empty?
197
+
198
+ if rem =~ /^([^\\\/]*[\\\/])/
199
+
200
+ parts << $1
201
+ rem = $'
202
+ else
200
203
 
201
- parts << rem
202
- rem = ''
203
- end
204
- end
205
-
206
- parts
207
- end
208
-
209
- # Returns a tuple consisting of the following
210
- # elements (or nil, for any element that is not)
211
- # present
212
- #
213
- # f1. Windows root, or nil
214
- # f2. directory, or nil
215
- # f3. basename, or nil
216
- # f4. basename-minus-extension, or nil
217
- # f5. extension, or nil
218
- # f6. array of directory path parts, which may be empty (not nil)
219
- # f7. array of all path parts, which may be empty (not nil)
220
- #
221
- # dependencies: Util.path_parts, Util.get_windows_root
222
- #
223
- # @!visibility private
224
- def self.split_path(p) # :nodoc:
204
+ parts << rem
205
+ rem = ''
206
+ end
207
+ end
208
+
209
+ parts
210
+ end
211
+
212
+ # Returns a tuple consisting of the following
213
+ # elements (or nil, for any element that is not)
214
+ # present
215
+ #
216
+ # f1. Windows root, or nil
217
+ # f2. directory, or nil
218
+ # f3. basename, or nil
219
+ # f4. basename-minus-extension, or nil
220
+ # f5. extension, or nil
221
+ # f6. array of directory path parts, which may be empty (not nil)
222
+ # f7. array of all path parts, which may be empty (not nil)
223
+ #
224
+ # dependencies: Util.path_parts, Util.get_windows_root
225
+ #
226
+ # @!visibility private
227
+ def self.split_path(p) # :nodoc:
225
228
 
226
- f1_windows_root, remainder = self.get_windows_root p
227
- f1_windows_root = nil if not f1_windows_root or f1_windows_root.empty?
228
- remainder = nil if not remainder or remainder.empty?
229
+ f1_windows_root, remainder = self.get_windows_root p
230
+ f1_windows_root = nil if not f1_windows_root or f1_windows_root.empty?
231
+ remainder = nil if not remainder or remainder.empty?
229
232
 
230
- if not remainder or remainder.empty?
233
+ if not remainder or remainder.empty?
231
234
 
232
- f2_directory = nil
233
- f3_basename = nil
234
- f4_nameonly = nil
235
- f5_extension = nil
236
- else
235
+ f2_directory = nil
236
+ f3_basename = nil
237
+ f4_nameonly = nil
238
+ f5_extension = nil
239
+ else
237
240
 
238
- if remainder =~ /^(.*[\\\/])([^\\\/]*)$/
241
+ if remainder =~ /^(.*[\\\/])([^\\\/]*)$/
239
242
 
240
- f2_directory = $1
241
- f3_basename = $2
242
- else
243
+ f2_directory = $1
244
+ f3_basename = $2
245
+ else
243
246
 
244
- f2_directory = nil
245
- f3_basename = remainder
246
- f4_nameonly = nil
247
- f5_extension = nil
248
- end
247
+ f2_directory = nil
248
+ f3_basename = remainder
249
+ f4_nameonly = nil
250
+ f5_extension = nil
251
+ end
249
252
 
250
- f2_directory = nil if not f2_directory or f2_directory.empty?
251
- f3_basename = nil if not f3_basename or f3_basename.empty?
253
+ f2_directory = nil if not f2_directory or f2_directory.empty?
254
+ f3_basename = nil if not f3_basename or f3_basename.empty?
252
255
 
253
- if f3_basename
256
+ if f3_basename
254
257
 
255
- # special case: treat '.' and '..' as file-name only
256
- if '.' == f3_basename or '..' == f3_basename
258
+ # special case: treat '.' and '..' as file-name only
259
+ if '.' == f3_basename or '..' == f3_basename
257
260
 
258
- f4_nameonly = f3_basename
259
- f5_extension = nil
260
- elsif f3_basename =~ /^(.*)(\.[^.]*)$/
261
+ f4_nameonly = f3_basename
262
+ f5_extension = nil
263
+ elsif f3_basename =~ /^(.*)(\.[^.]*)$/
261
264
 
262
- f4_nameonly = $1
263
- f5_extension = $2
264
- else
265
+ f4_nameonly = $1
266
+ f5_extension = $2
267
+ else
265
268
 
266
- f4_nameonly = f3_basename
267
- f5_extension = nil
268
- end
269
- else
269
+ f4_nameonly = f3_basename
270
+ f5_extension = nil
271
+ end
272
+ else
270
273
 
271
- f4_nameonly = nil
272
- f5_extension = nil
273
- end
274
- end
274
+ f4_nameonly = nil
275
+ f5_extension = nil
276
+ end
277
+ end
275
278
 
276
- f4_nameonly = nil if not f4_nameonly or f4_nameonly.empty?
277
- f5_extension = nil if not f5_extension or f5_extension.empty?
278
- f6_directory_parts = self.path_parts(f2_directory)
279
- f7_path_parts = self.path_parts(p)
279
+ f4_nameonly = nil if not f4_nameonly or f4_nameonly.empty?
280
+ f5_extension = nil if not f5_extension or f5_extension.empty?
281
+ f6_directory_parts = self.path_parts(f2_directory)
282
+ f7_path_parts = self.path_parts(p)
280
283
 
281
- return [ f1_windows_root, f2_directory, f3_basename, f4_nameonly, f5_extension, f6_directory_parts, f7_path_parts ]
282
- end
284
+ return [ f1_windows_root, f2_directory, f3_basename, f4_nameonly, f5_extension, f6_directory_parts, f7_path_parts ]
285
+ end
283
286
 
284
- # Returns a tuple consisting of:
285
- #
286
- # f1. The canonicalised array of parts
287
- # f2. A boolean indicating whether to 'consume' the basename
288
- #
289
- # dependencies: OS.is_root_dir_, OS.get_number_of_dots_dir_,
290
- #
291
- # @!visibility private
292
- def self.canonicalise_parts(parts, basename = nil) # :nodoc:
287
+ # Returns a tuple consisting of:
288
+ #
289
+ # f1. The canonicalised array of parts
290
+ # f2. A boolean indicating whether to 'consume' the basename
291
+ #
292
+ # dependencies: OS.is_root_dir_, OS.get_number_of_dots_dir_,
293
+ #
294
+ # @!visibility private
295
+ def self.canonicalise_parts(parts, basename = nil) # :nodoc:
293
296
 
294
- newParts = []
297
+ newParts = []
295
298
 
296
- lastSingleDots = nil
299
+ lastSingleDots = nil
297
300
 
298
- path_is_rooted = nil
301
+ path_is_rooted = nil
299
302
 
300
- index = -1
301
- parts.each do |part|
303
+ index = -1
304
+ parts.each do |part|
302
305
 
303
- index += 1
306
+ index += 1
304
307
 
305
- next if not part
306
- next if part.empty?
308
+ next if not part
309
+ next if part.empty?
307
310
 
308
- if path_is_rooted.nil?
311
+ if path_is_rooted.nil?
309
312
 
310
- path_is_rooted = self.is_path_name_separator(part[0])
311
- end
313
+ path_is_rooted = self.is_path_name_separator(part[0])
314
+ end
312
315
 
313
- if ?. == part[0]
316
+ if ?. == part[0]
314
317
 
315
- if self.is_path_name_separator(part[1])
318
+ if self.is_path_name_separator(part[1])
316
319
 
317
- # single dots, so ...
320
+ # single dots, so ...
318
321
 
319
- # ... remember the last instance, and ...
320
- lastSingleDots = part
322
+ # ... remember the last instance, and ...
323
+ lastSingleDots = part
321
324
 
322
- # ... skip to leave this out of the result
323
- next
324
- elsif ?. == part[1]
325
+ # ... skip to leave this out of the result
326
+ next
327
+ elsif ?. == part[1]
325
328
 
326
- if self.is_path_name_separator(part[2])
329
+ if self.is_path_name_separator(part[2])
327
330
 
328
- # double dots, so ...
329
- # ... skip this and pop prior from the new list iff:
330
- #
331
- # 1. there is a prior elements in the new list (size > 1); AND
332
- # 2. the last element in the new list is not the root directory; AND
333
- # 3. the last element in the list is not a dots directory
334
- if not newParts.empty? # 1.
331
+ # double dots, so ...
332
+ # ... skip this and pop prior from the new list iff:
333
+ #
334
+ # 1. there is a prior elements in the new list (size > 1); AND
335
+ # 2. the last element in the new list is not the root directory; AND
336
+ # 3. the last element in the list is not a dots directory
337
+ if not newParts.empty? # 1.
335
338
 
336
- priorPart = newParts[-1]
337
- if 1 == newParts.size and OS.is_root_dir_(priorPart)
339
+ priorPart = newParts[-1]
340
+ if 1 == newParts.size and OS.is_root_dir_(priorPart)
338
341
 
339
- # 2.
340
- next
341
- else
342
+ # 2.
343
+ next
344
+ else
342
345
 
343
- dirtype = OS.get_number_of_dots_dir_(priorPart)
344
- if 0 == dirtype # 3.
346
+ dirtype = OS.get_number_of_dots_dir_(priorPart)
347
+ if 0 == dirtype # 3.
345
348
 
346
- if newParts.pop
349
+ if newParts.pop
347
350
 
348
- next
349
- end
350
- end
351
- end
352
- end
353
- else
351
+ next
352
+ end
353
+ end
354
+ end
355
+ end
356
+ else
354
357
 
355
- # it's a ..X part
356
- end
357
- else
358
+ # it's a ..X part
359
+ end
360
+ else
358
361
 
359
- # it's a .X part
360
- end
361
- else
362
+ # it's a .X part
363
+ end
364
+ else
362
365
 
363
- # it's a non-dots part
364
- end
366
+ # it's a non-dots part
367
+ end
365
368
 
366
- newParts << part
367
- end
369
+ newParts << part
370
+ end
368
371
 
369
- consume_basename = false
372
+ consume_basename = false
370
373
 
371
- if basename
374
+ if basename
372
375
 
373
- if ?. == basename[0]
376
+ if ?. == basename[0]
374
377
 
375
- if 1 == basename.size
378
+ if 1 == basename.size
376
379
 
377
- # single dots
378
- if newParts.empty?
380
+ # single dots
381
+ if newParts.empty?
379
382
 
380
- lastSingleDots = false
381
- else
383
+ lastSingleDots = false
384
+ else
382
385
 
383
- consume_basename = true
384
- end
385
- elsif ?. == basename[1] and 2 == basename.size
386
+ consume_basename = true
387
+ end
388
+ elsif ?. == basename[1] and 2 == basename.size
386
389
 
387
- # double dots, so ...
388
- #
389
- # ... pop unless we already have some outstanding double dots
390
- if newParts.empty?
390
+ # double dots, so ...
391
+ #
392
+ # ... pop unless we already have some outstanding double dots
393
+ if newParts.empty?
391
394
 
392
- newParts << '..'
393
- consume_basename = true
394
- elsif 1 == newParts.size && 1 == newParts[0].size && Util.is_path_name_separator(newParts[0][0])
395
+ newParts << '..'
396
+ consume_basename = true
397
+ elsif 1 == newParts.size && 1 == newParts[0].size && Util.is_path_name_separator(newParts[0][0])
395
398
 
396
- consume_basename = true
397
- else
399
+ consume_basename = true
400
+ else
398
401
 
399
- if 2 != OS.get_number_of_dots_dir_(newParts[-1])
402
+ if 2 != OS.get_number_of_dots_dir_(newParts[-1])
400
403
 
401
- newParts.pop
402
- consume_basename = true
403
- end
404
- end
405
- end
406
- end
407
- end
404
+ newParts.pop
405
+ consume_basename = true
406
+ end
407
+ end
408
+ end
409
+ end
410
+ end
408
411
 
409
- # push lastSingleDots (which may contain a trailing slash) if
410
- # exists and newParts is empty
411
- newParts << lastSingleDots if lastSingleDots and newParts.empty?
412
+ # push lastSingleDots (which may contain a trailing slash) if
413
+ # exists and newParts is empty
414
+ newParts << lastSingleDots if lastSingleDots and newParts.empty?
412
415
 
413
- if not newParts.empty?
416
+ if not newParts.empty?
414
417
 
415
- if 2 == OS.get_number_of_dots_dir_(newParts[-1])
418
+ if 2 == OS.get_number_of_dots_dir_(newParts[-1])
416
419
 
417
- # the last element is the double-dots directory, but
418
- # need to determine whether to ensure/remote a
419
- # trailing slash
420
- if basename and not basename.empty?
420
+ # the last element is the double-dots directory, but
421
+ # need to determine whether to ensure/remote a
422
+ # trailing slash
423
+ if basename and not basename.empty?
421
424
 
422
- if not consume_basename
425
+ if not consume_basename
423
426
 
424
- # leave as is
425
- else
427
+ # leave as is
428
+ else
426
429
 
427
- #
428
- newParts[-1] = '..'
429
- end
430
- end
431
- end
432
- else
430
+ newParts[-1] = '..'
431
+ end
432
+ end
433
+ end
434
+ else
433
435
 
434
- # handle case where all (double)-dots have eliminated
435
- # all regular directories
436
- if not basename or basename.empty? or consume_basename
436
+ # handle case where all (double)-dots have eliminated
437
+ # all regular directories
438
+ if not basename or basename.empty? or consume_basename
437
439
 
438
- newParts << '.'
439
- end
440
- end
440
+ newParts << '.'
441
+ end
442
+ end
441
443
 
442
- [ newParts.join(''), consume_basename ]
443
- end
444
- end # module Util
444
+ [ newParts.join(''), consume_basename ]
445
+ end
446
+ end # module Util
445
447
 
446
- # Canonicalises a path
447
- #
448
- # Note: contains a trailing slash if, in the context of the given
449
- # path, the last element of the canonicalised path is a directory
450
- # unequivocally
451
- #
452
- # @!visibility private
453
- def self.canonicalise_path(path) # :nodoc:
448
+ # Canonicalises a path
449
+ #
450
+ # Note: contains a trailing slash if, in the context of the given
451
+ # path, the last element of the canonicalised path is a directory
452
+ # unequivocally
453
+ #
454
+ # @!visibility private
455
+ def self.canonicalise_path(path) # :nodoc:
454
456
 
455
- return nil if not path
456
- return '' if path.empty?
457
+ return nil if not path
458
+ return '' if path.empty?
457
459
 
458
- path = File.expand_path(path) if '~' == path[0].to_s
460
+ path = File.expand_path(path) if '~' == path[0].to_s
459
461
 
460
- f1_windows_root, f2_directory, f3_basename, dummy1, dummy2, directory_parts, dummy3 = Util.split_path(path)
462
+ f1_windows_root, f2_directory, f3_basename, dummy1, dummy2, directory_parts, dummy3 = Util.split_path(path)
461
463
 
462
- # suppress unused warnings
463
- dummy1 = dummy1
464
- dummy2 = dummy2
465
- dummy3 = dummy3
464
+ # suppress unused warnings
465
+ dummy1 = dummy1
466
+ dummy2 = dummy2
467
+ dummy3 = dummy3
466
468
 
467
- if not f2_directory
469
+ if not f2_directory
468
470
 
469
- canonicalised_directory = nil
470
- else
471
+ canonicalised_directory = nil
472
+ else
471
473
 
472
- canonicalised_directory, consume_basename = Util.canonicalise_parts(directory_parts, f3_basename)
473
- f3_basename = nil if consume_basename
474
- end
474
+ canonicalised_directory, consume_basename = Util.canonicalise_parts(directory_parts, f3_basename)
475
+ f3_basename = nil if consume_basename
476
+ end
475
477
 
476
- return "#{f1_windows_root}#{canonicalised_directory}#{f3_basename}"
477
- end
478
+ return "#{f1_windows_root}#{canonicalised_directory}#{f3_basename}"
479
+ end
478
480
 
479
- # @!visibility private
480
- def self.absolute_path?(path) # :nodoc:
481
+ # @!visibility private
482
+ def self.absolute_path?(path) # :nodoc:
481
483
 
482
- case path
483
- when nil
484
+ case path
485
+ when nil
484
486
 
485
- return nil
486
- when ::String
487
+ return nil
488
+ when ::String
487
489
 
488
- return nil if path.empty?
490
+ return nil if path.empty?
489
491
 
490
- path = File.expand_path(path) if '~' == path[0]
491
- when ::Recls::Entry
492
+ path = File.expand_path(path) if '~' == path[0]
493
+ when ::Recls::Entry
492
494
 
493
- return path
494
- else
495
+ return path
496
+ else
495
497
 
496
- raise TypeError, "parameter path ('#{path}') is of type #{path.class} must be nil or an instance of #{::String} or #{::Recls::Entry}"
497
- end
498
+ raise TypeError, "parameter path ('#{path}') is of type #{path.class} must be nil or an instance of #{::String} or #{::Recls::Entry}"
499
+ end
498
500
 
499
- f1_windows_root, f2_directory, dummy1, dummy2, dummy3, dummy4, dummy5 = Util.split_path(path)
501
+ f1_windows_root, f2_directory, dummy1, dummy2, dummy3, dummy4, dummy5 = Util.split_path(path)
500
502
 
501
- dummy1 = dummy2 = dummy3 = dummy4 = dummy5 = nil
503
+ dummy1 = dummy2 = dummy3 = dummy4 = dummy5 = nil
502
504
 
503
- unless f1_windows_root
505
+ unless f1_windows_root
504
506
 
505
- return nil unless f2_directory
507
+ return nil unless f2_directory
506
508
 
507
- return nil unless Util.is_path_name_separator(f2_directory[0])
508
- end
509
+ return nil unless Util.is_path_name_separator(f2_directory[0])
510
+ end
509
511
 
510
- Recls::Ximpl.stat_prep(path, nil, Recls::DETAILS_LATER)
511
- end
512
+ Recls::Ximpl.stat_prep(path, nil, Recls::DETAILS_LATER)
513
+ end
512
514
 
513
- # determines the absolute path of a given path
514
- #
515
- # @!visibility private
516
- def self.absolute_path(path, refdir = nil) # :nodoc:
515
+ # determines the absolute path of a given path
516
+ #
517
+ # @!visibility private
518
+ def self.absolute_path(path, refdir = nil) # :nodoc:
517
519
 
518
- case path
519
- when ::NilClass
520
+ case path
521
+ when ::NilClass
520
522
 
521
- return nil
522
- when ::String
523
+ return nil
524
+ when ::String
523
525
 
524
- path = File.expand_path(path) if '~' == path[0]
525
- when ::Recls::Entry
526
+ path = File.expand_path(path) if '~' == path[0]
527
+ when ::Recls::Entry
526
528
 
527
- return path.path
528
- else
529
+ return path.path
530
+ else
529
531
 
530
- raise TypeError, "parameter path ('#{path}') is of type #{path.class} must be an instance of #{::String} or Recls::Entry"
531
- end
532
+ raise TypeError, "parameter path ('#{path}') is of type #{path.class} must be an instance of #{::String} or Recls::Entry"
533
+ end
532
534
 
533
- return '' if path.empty?
535
+ return '' if path.empty?
534
536
 
535
- dummy1, f2_directory, dummy2, dummy3, dummy4, dummy5, dummy6 = Util.split_path(path)
537
+ dummy1, f2_directory, dummy2, dummy3, dummy4, dummy5, dummy6 = Util.split_path(path)
536
538
 
537
- # suppress unused warnings
538
- dummy1 = dummy1
539
- dummy2 = dummy2
540
- dummy3 = dummy3
541
- dummy4 = dummy4
542
- dummy5 = dummy5
543
- dummy6 = dummy6
539
+ # suppress unused warnings
540
+ dummy1 = dummy1
541
+ dummy2 = dummy2
542
+ dummy3 = dummy3
543
+ dummy4 = dummy4
544
+ dummy5 = dummy5
545
+ dummy6 = dummy6
544
546
 
545
- if f2_directory =~ /^[\\\/]/
547
+ if f2_directory =~ /^[\\\/]/
546
548
 
547
- return path
548
- end
549
+ return path
550
+ end
549
551
 
550
- cwd = refdir ? refdir : Dir.getwd
552
+ cwd = refdir ? refdir : Dir.getwd
551
553
 
552
- trailing_slash = Util.get_trailing_slash(path)
554
+ trailing_slash = Util.get_trailing_slash(path)
553
555
 
554
- if '.' == path
556
+ if '.' == path
555
557
 
556
- return Util.trim_trailing_slash cwd
557
- elsif 2 == path.size and trailing_slash
558
+ return Util.trim_trailing_slash cwd
559
+ elsif 2 == path.size and trailing_slash
558
560
 
559
- return Util.append_trailing_slash(cwd, path[1..1])
560
- end
561
+ return Util.append_trailing_slash(cwd, path[1..1])
562
+ end
561
563
 
562
- cwd = Util.append_trailing_slash(cwd)
564
+ cwd = Util.append_trailing_slash(cwd)
563
565
 
564
- path = "#{cwd}#{path}"
566
+ path = "#{cwd}#{path}"
565
567
 
566
- path = canonicalise_path path
568
+ path = canonicalise_path path
567
569
 
568
- if trailing_slash
570
+ if trailing_slash
569
571
 
570
- path = Util.append_trailing_slash path, trailing_slash
571
- else
572
+ path = Util.append_trailing_slash path, trailing_slash
573
+ else
572
574
 
573
- path = Util.trim_trailing_slash path
574
- end
575
+ path = Util.trim_trailing_slash path
576
+ end
575
577
 
576
- path
577
- end
578
+ path
579
+ end
578
580
 
579
- # obtains the basename of a path, e.g.
580
- # the basename of
581
- # abc/def/ghi.jkl
582
- # or (on Windows)
583
- # C:\abc\def\ghi.jkl
584
- # is
585
- # ghi.jkl
586
- #
587
- # @!visibility private
588
- def self.basename(path) # :nodoc:
581
+ # obtains the basename of a path, e.g.
582
+ # the basename of
583
+ # abc/def/ghi.jkl
584
+ # or (on Windows)
585
+ # C:\abc\def\ghi.jkl
586
+ # is
587
+ # ghi.jkl
588
+ #
589
+ # @!visibility private
590
+ def self.basename(path) # :nodoc:
589
591
 
590
- return nil if not path
592
+ return nil if not path
591
593
 
592
- # NOTE: we don't implement in terms of split_path
593
- # because all but the UNC case work with just
594
- # detecting the last (back)slash
594
+ # NOTE: we don't implement in terms of split_path
595
+ # because all but the UNC case work with just
596
+ # detecting the last (back)slash
595
597
 
596
- if Recls::Ximpl::OS::OS_IS_WINDOWS
598
+ if Recls::Ximpl::OS::OS_IS_WINDOWS
597
599
 
598
- wr, rem = Util.get_windows_root(path)
600
+ wr, rem = Util.get_windows_root(path)
599
601
 
600
- # suppress unused warning
601
- wr = wr
602
+ # suppress unused warning
603
+ wr = wr
602
604
 
603
- if not rem
605
+ if not rem
604
606
 
605
- return ''
606
- else
607
+ return ''
608
+ else
607
609
 
608
- path = rem
609
- end
610
- end
610
+ path = rem
611
+ end
612
+ end
611
613
 
612
- if not path.is_a? String
614
+ if not path.is_a? String
613
615
 
614
- path = path.to_s
615
- end
616
+ path = path.to_s
617
+ end
616
618
 
617
- if path =~ /^.*[\/\\](.*)/
619
+ if path =~ /^.*[\/\\](.*)/
618
620
 
619
- $1
620
- else
621
+ $1
622
+ else
621
623
 
622
- path
623
- end
624
- end
624
+ path
625
+ end
626
+ end
625
627
 
626
- # obtains the file extension of a basename, e.g.
627
- # the file_ext of
628
- # ghi.jkl
629
- # is
630
- # .jkl
631
- #
632
- # @!visibility private
633
- def self.file_ext(path) # :nodoc:
628
+ # obtains the file extension of a basename, e.g.
629
+ # the file_ext of
630
+ # ghi.jkl
631
+ # is
632
+ # .jkl
633
+ #
634
+ # @!visibility private
635
+ def self.file_ext(path) # :nodoc:
634
636
 
635
- return nil if not path
637
+ return nil if not path
636
638
 
637
- use_split_path = false
639
+ use_split_path = false
638
640
 
639
- if Recls::Ximpl::OS::OS_IS_WINDOWS
641
+ if Recls::Ximpl::OS::OS_IS_WINDOWS
640
642
 
641
- if path.include? ?\\
643
+ if path.include? ?\\
642
644
 
643
- use_split_path = true
644
- end
645
- end
645
+ use_split_path = true
646
+ end
647
+ end
646
648
 
647
- if path.include? ?/
649
+ if path.include? ?/
648
650
 
649
- use_split_path = true
650
- end
651
+ use_split_path = true
652
+ end
651
653
 
652
- if use_split_path
654
+ if use_split_path
653
655
 
654
- ext = Util.split_path(path)[4]
655
- else
656
+ ext = Util.split_path(path)[4]
657
+ else
656
658
 
657
- if path =~ /^.*(\.[^.]*)$/
659
+ if path =~ /^.*(\.[^.]*)$/
658
660
 
659
- ext = $1
660
- else
661
+ ext = $1
662
+ else
661
663
 
662
- ext = nil
663
- end
664
- end
664
+ ext = nil
665
+ end
666
+ end
665
667
 
666
- return ext ? ext : ''
667
- end
668
+ return ext ? ext : ''
669
+ end
668
670
 
669
- # obtains the directory from the directory path
670
- #
671
- # @!visibility private
672
- def self.directory_from_directory_path(directory_path) # :nodoc:
671
+ # obtains the directory from the directory path
672
+ #
673
+ # @!visibility private
674
+ def self.directory_from_directory_path(directory_path) # :nodoc:
673
675
 
674
- wr, rem = Util.get_windows_root(directory_path)
676
+ wr, rem = Util.get_windows_root(directory_path)
675
677
 
676
- # suppress unused warning
677
- wr = wr
678
+ # suppress unused warning
679
+ wr = wr
678
680
 
679
- rem
680
- end
681
+ rem
682
+ end
681
683
 
682
- # obtains the directory parts from a directory
683
- #
684
- # @!visibility private
685
- def self.directory_parts_from_directory(directory) # :nodoc:
684
+ # obtains the directory parts from a directory
685
+ #
686
+ # @!visibility private
687
+ def self.directory_parts_from_directory(directory) # :nodoc:
686
688
 
687
- return nil if not directory
689
+ return nil if not directory
688
690
 
689
- directory_parts = []
691
+ directory_parts = []
690
692
 
691
- until directory.empty?
693
+ until directory.empty?
692
694
 
693
- if directory =~ /^([^\\\/]*[\\\/])/
695
+ if directory =~ /^([^\\\/]*[\\\/])/
694
696
 
695
- directory_parts << $1
696
- directory = $'
697
- else
697
+ directory_parts << $1
698
+ directory = $'
699
+ else
698
700
 
699
- directory_parts << directory
700
- directory = ''
701
- end
702
- end
701
+ directory_parts << directory
702
+ directory = ''
703
+ end
704
+ end
703
705
 
704
- directory_parts
705
- end
706
+ directory_parts
707
+ end
706
708
 
707
- # obtains the relative path of a given path and
708
- # a reference directory
709
- #
710
- # @!visibility private
711
- def self.derive_relative_path(origin, path) # :nodoc:
709
+ # obtains the relative path of a given path and
710
+ # a reference directory
711
+ #
712
+ # @!visibility private
713
+ def self.derive_relative_path(origin, path) # :nodoc:
712
714
 
713
- return nil if path.nil?
714
- return nil if path.empty?
715
- return path if origin.nil?
716
- return path if origin.empty?
715
+ return nil if path.nil?
716
+ return nil if path.empty?
717
+ return path if origin.nil?
718
+ return path if origin.empty?
717
719
 
718
- path = self.canonicalise_path path
719
- origin = self.canonicalise_path origin
720
+ path = self.canonicalise_path path
721
+ origin = self.canonicalise_path origin
720
722
 
721
- path = self.absolute_path path
722
- origin = self.absolute_path origin
723
+ path = self.absolute_path path
724
+ origin = self.absolute_path origin
723
725
 
724
- return path if /^\.[\\\/]*$/ =~ origin
726
+ return path if /^\.[\\\/]*$/ =~ origin
725
727
 
726
- path_splits = Util.split_path(path)
727
- origin_splits = Util.split_path(origin)
728
+ path_splits = Util.split_path(path)
729
+ origin_splits = Util.split_path(origin)
728
730
 
729
- # if different windows root, then cannot provide relative
731
+ # if different windows root, then cannot provide relative
730
732
 
731
- if path_splits[0] and origin_splits[0]
733
+ if path_splits[0] and origin_splits[0]
732
734
 
733
- return path if path_splits[0] != origin_splits[0]
734
- end
735
+ return path if path_splits[0] != origin_splits[0]
736
+ end
735
737
 
736
- trailing_slash = Util.get_trailing_slash(path)
738
+ trailing_slash = Util.get_trailing_slash(path)
737
739
 
738
- path_parts = path_splits[6]
739
- origin_parts = origin_splits[6]
740
+ path_parts = path_splits[6]
741
+ origin_parts = origin_splits[6]
740
742
 
741
- loop do
743
+ loop do
742
744
 
743
- break if path_parts.empty?
744
- break if origin_parts.empty?
745
+ break if path_parts.empty?
746
+ break if origin_parts.empty?
745
747
 
746
- path_part = path_parts[0]
747
- origin_part = origin_parts[0]
748
+ path_part = path_parts[0]
749
+ origin_part = origin_parts[0]
748
750
 
749
- if 1 == path_parts.size || 1 == origin_parts.size
751
+ if 1 == path_parts.size || 1 == origin_parts.size
750
752
 
751
- path_part = Util.append_trailing_slash(path_part)
752
- origin_part = Util.append_trailing_slash(origin_part)
753
- end
753
+ path_part = Util.append_trailing_slash(path_part)
754
+ origin_part = Util.append_trailing_slash(origin_part)
755
+ end
754
756
 
755
- if path_part == origin_part
757
+ if path_part == origin_part
756
758
 
757
- path_parts.shift
758
- origin_parts.shift
759
- else
759
+ path_parts.shift
760
+ origin_parts.shift
761
+ else
760
762
 
761
- break
762
- end
763
- end
763
+ break
764
+ end
765
+ end
764
766
 
765
- return ".#{trailing_slash}" if path_parts.empty? and origin_parts.empty?
767
+ return ".#{trailing_slash}" if path_parts.empty? and origin_parts.empty?
766
768
 
767
- # at this point, all reference parts should be converted into '..'
769
+ # at this point, all reference parts should be converted into '..'
768
770
 
769
- return origin_parts.map { |rp| '..' }.join('/') if path_parts.empty?
771
+ return origin_parts.map { |rp| '..' }.join('/') if path_parts.empty?
770
772
 
771
- return '../' * origin_parts.size + path_parts.join('')
772
- end
773
+ return '../' * origin_parts.size + path_parts.join('')
774
+ end
773
775
 
774
- # @!visibility private
775
- def self.combine_paths(paths, options) # :nodoc:
776
+ # @!visibility private
777
+ def self.combine_paths(paths, options) # :nodoc:
776
778
 
777
- paths = [ paths ] unless ::Array === paths
778
- abs_ix = 0
779
+ paths = [ paths ] unless ::Array === paths
780
+ abs_ix = 0
779
781
 
780
- paths = paths.map { |path| '~' == path[0].to_s ? File.expand_path(path) : path }
782
+ paths = paths.map { |path| '~' == path[0].to_s ? File.expand_path(path) : path }
781
783
 
782
- paths.each_with_index do |path, index|
784
+ paths.each_with_index do |path, index|
783
785
 
784
- dummy1, f2_directory, dummy2, dummy3, dummy4, dummy5, dummy6 = Util.split_path(path)
786
+ dummy1, f2_directory, dummy2, dummy3, dummy4, dummy5, dummy6 = Util.split_path(path)
785
787
 
786
- # suppress unused warnings
787
- dummy1 = dummy1
788
- dummy2 = dummy2
789
- dummy3 = dummy3
790
- dummy4 = dummy4
791
- dummy5 = dummy5
792
- dummy6 = dummy6
788
+ # suppress unused warnings
789
+ dummy1 = dummy1
790
+ dummy2 = dummy2
791
+ dummy3 = dummy3
792
+ dummy4 = dummy4
793
+ dummy5 = dummy5
794
+ dummy6 = dummy6
793
795
 
794
- if f2_directory && Util.is_path_name_separator(f2_directory[0])
796
+ if f2_directory && Util.is_path_name_separator(f2_directory[0])
795
797
 
796
- abs_ix = index
797
- end
798
- end
798
+ abs_ix = index
799
+ end
800
+ end
799
801
 
800
- paths = paths[abs_ix..-1]
802
+ paths = paths[abs_ix..-1]
801
803
 
802
- r = File.join(*paths)
804
+ r = File.join(*paths)
803
805
 
804
- cap = options[:canonicalise] || options[:canonicalize]
806
+ cap = options[:canonicalise] || options[:canonicalize]
805
807
 
806
- if cap
808
+ if cap
807
809
 
808
- r = Recls.canonicalise_path r
809
- else
810
+ r = Recls.canonicalise_path r
811
+ else
810
812
 
811
- clp = options[:clean] || options[:clean_path]
813
+ clp = options[:clean] || options[:clean_path]
812
814
 
813
- if clp
815
+ if clp
814
816
 
815
- r = Pathname.new(r).cleanpath.to_s
816
- end
817
- end
817
+ r = Pathname.new(r).cleanpath.to_s
818
+ end
819
+ end
818
820
 
819
- r
820
- end
821
+ r
822
+ end
821
823
 
822
824
 
823
- # Elicits the contents of the given directory, or, if the flag
824
- # STOP_ON_ACCESS_FAILURE is specified throws an exception if the
825
- # directory does not exist
826
- #
827
- # Some known conditions:
828
- #
829
- # * (Mac OSX) /dev/fd/<N> - some of these stat() as directories but
830
- # Dir.new fails with ENOTDIR
831
- #
832
- # @!visibility private
833
- def self.dir_entries_maybe(dir, flags) # :nodoc:
825
+ # Elicits the contents of the given directory, or, if the flag
826
+ # STOP_ON_ACCESS_FAILURE is specified throws an exception if the
827
+ # directory does not exist
828
+ #
829
+ # Some known conditions:
830
+ #
831
+ # * (Mac OSX) /dev/fd/<N> - some of these stat() as directories but
832
+ # Dir.new fails with ENOTDIR
833
+ #
834
+ # @!visibility private
835
+ def self.dir_entries_maybe(dir, flags) # :nodoc:
834
836
 
835
- begin
837
+ begin
836
838
 
837
- Dir.new(dir).to_a
839
+ Dir.new(dir).to_a
838
840
 
839
- rescue SystemCallError => x
841
+ rescue SystemCallError => x
840
842
 
841
- $stderr.puts "exception (#{x.class}): #{x}" if $DEBUG
843
+ $stderr.puts "exception (#{x.class}): #{x}" if $DEBUG
842
844
 
843
- if(0 != (STOP_ON_ACCESS_FAILURE & flags))
845
+ if(0 != (STOP_ON_ACCESS_FAILURE & flags))
844
846
 
845
- raise
846
- end
847
+ raise
848
+ end
847
849
 
848
- return []
849
- end
850
- end
850
+ return []
851
+ end
852
+ end
851
853
 
852
- # @!visibility private
853
- def self.stat_prep(path, search_root, flags) # :nodoc:
854
+ # @!visibility private
855
+ def self.stat_prep(path, search_root, flags) # :nodoc:
854
856
 
855
- begin
857
+ begin
856
858
 
857
- Recls::Entry.new(path, Recls::Ximpl::FileStat.stat(path), search_root, flags)
858
- rescue Errno::ENOENT, Errno::ENXIO => x
859
+ Recls::Entry.new(path, Recls::Ximpl::FileStat.stat(path), search_root, flags)
860
+ rescue Errno::ENOENT, Errno::ENXIO => x
859
861
 
860
- x = x # suppress warning
862
+ x = x # suppress warning
861
863
 
862
- if 0 != (flags & Recls::DETAILS_LATER)
864
+ if 0 != (flags & Recls::DETAILS_LATER)
863
865
 
864
- Recls::Entry.new(path, nil, search_root, flags)
865
- else
866
+ Recls::Entry.new(path, nil, search_root, flags)
867
+ else
866
868
 
867
- nil
868
- end
869
- end
870
- end
871
- end # module Ximpl
869
+ nil
870
+ end
871
+ end
872
+ end
873
+ end # module Ximpl
874
+ end # module Recls
872
875
 
873
876
  # :startdoc:
874
877
 
875
- end # module Recls
876
878
 
877
879
  # ############################## end of file ############################# #
878
880
 
879
-