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