recls-ruby 2.12.0 → 2.12.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
-