recls-ruby 2.8.2 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +57 -10
  3. data/examples/find_files_and_directories.md +77 -0
  4. data/examples/find_files_and_directories.rb +19 -0
  5. data/examples/find_files_and_directories.recursive.md +304 -0
  6. data/examples/find_files_and_directories.recursive.rb +19 -0
  7. data/examples/show_hidden_files.md +39 -0
  8. data/examples/show_hidden_files.rb +2 -2
  9. data/examples/show_readonly_files.md +35 -0
  10. data/examples/show_readonly_files.rb +2 -2
  11. data/lib/recls.rb +2 -0
  12. data/lib/recls/api.rb +70 -3
  13. data/lib/recls/combine_paths_1.rb +70 -0
  14. data/lib/recls/combine_paths_2plus.rb +76 -0
  15. data/lib/recls/entry.rb +40 -4
  16. data/lib/recls/file_search.rb +48 -14
  17. data/lib/recls/flags.rb +21 -4
  18. data/lib/recls/foreach.rb +45 -6
  19. data/lib/recls/obsolete.rb +119 -0
  20. data/lib/recls/recls.rb +27 -56
  21. data/lib/recls/stat.rb +96 -24
  22. data/lib/recls/util.rb +74 -23
  23. data/lib/recls/version.rb +10 -4
  24. data/lib/recls/ximpl/os.rb +29 -15
  25. data/lib/recls/ximpl/unix.rb +29 -16
  26. data/lib/recls/ximpl/util.rb +141 -39
  27. data/lib/recls/ximpl/windows.rb +56 -25
  28. data/test/fixtures/readonly/file-1 +0 -0
  29. data/test/fixtures/readonly/file-2 +0 -0
  30. data/test/scratch/test_display_parts.rb +9 -9
  31. data/test/scratch/test_entry.rb +11 -9
  32. data/test/scratch/test_files_and_directories.rb +17 -14
  33. data/test/scratch/test_foreach.rb +0 -3
  34. data/test/scratch/test_module_function.rb +10 -10
  35. data/test/scratch/test_pattern_arrays.rb +32 -0
  36. data/test/scratch/test_show_dev_and_ino.rb +1 -1
  37. data/test/scratch/test_show_hidden.rb +3 -3
  38. data/test/unit/tc_recls_util.rb +6 -0
  39. data/test/unit/tc_recls_ximpl_util.rb +156 -101
  40. data/test/unit/ts_all.rb +11 -9
  41. metadata +36 -11
@@ -1,14 +1,14 @@
1
1
  # ######################################################################### #
2
- # File: recls/ximpl/util.rb
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: 25th January 2018
6
+ # Created: 24th July 2012
7
+ # Updated: 14th April 2019
8
8
  #
9
- # Author: Matthew Wilson
9
+ # Author: Matthew Wilson
10
10
  #
11
- # Copyright (c) 2012-2018, Matthew Wilson and Synesis Software
11
+ # Copyright (c) 2012-2019, Matthew Wilson and Synesis Software
12
12
  # All rights reserved.
13
13
  #
14
14
  # Redistribution and use in source and binary forms, with or without
@@ -41,13 +41,19 @@ require 'recls/flags'
41
41
 
42
42
  require 'pathname'
43
43
 
44
- module Recls
44
+ =begin
45
+ =end
46
+
47
+ module Recls # :nodoc:
45
48
 
46
- module Ximpl
49
+ # :stopdoc:
47
50
 
48
- module Util
51
+ module Ximpl # :nodoc: all
49
52
 
50
- def self.is_path_name_separator(c)
53
+ module Util # :nodoc: all
54
+
55
+ # @!visibility private
56
+ def self.is_path_name_separator(c) # :nodoc:
51
57
 
52
58
  return true if ?/ == c
53
59
 
@@ -62,7 +68,9 @@ module Recls
62
68
  # Indicates whether a trailing slash is on the given path
63
69
  #
64
70
  # dependencies: none
65
- def self.has_trailing_slash(p)
71
+ #
72
+ # @!visibility private
73
+ def self.has_trailing_slash(p) # :nodoc:
66
74
 
67
75
  return p if p.nil? or p.empty?
68
76
 
@@ -72,7 +80,9 @@ module Recls
72
80
  # returns the trailing slash, or nil if none present
73
81
  #
74
82
  # dependencies: none
75
- def self.get_trailing_slash(p, args = {})
83
+ #
84
+ # @!visibility private
85
+ def self.get_trailing_slash(p, args = {}) # :nodoc:
76
86
 
77
87
  return nil if p.nil?
78
88
  return nil if p.empty?
@@ -84,7 +94,9 @@ module Recls
84
94
  # present
85
95
  #
86
96
  # dependencies: none
87
- def self.append_trailing_slash(p, slash = nil)
97
+ #
98
+ # @!visibility private
99
+ def self.append_trailing_slash(p, slash = nil) # :nodoc:
88
100
 
89
101
  return p if not p or p.empty?
90
102
 
@@ -99,7 +111,9 @@ module Recls
99
111
  # root
100
112
  #
101
113
  # dependencies: none
102
- def self.trim_trailing_slash(p)
114
+ #
115
+ # @!visibility private
116
+ def self.trim_trailing_slash(p) # :nodoc:
103
117
 
104
118
  return p if not p or p.empty?
105
119
 
@@ -117,7 +131,9 @@ module Recls
117
131
  # [ nil, nil ] if p is nil
118
132
  #
119
133
  # dependencies: none
120
- def self.get_windows_root(p)
134
+ #
135
+ # @!visibility private
136
+ def self.get_windows_root(p) # :nodoc:
121
137
 
122
138
  return [ nil, nil ] if not p
123
139
 
@@ -161,7 +177,9 @@ module Recls
161
177
 
162
178
  # obtains the parts from a path, including any Windows root and
163
179
  # the file basename
164
- def self.path_parts(path)
180
+ #
181
+ # @!visibility private
182
+ def self.path_parts(path) # :nodoc:
165
183
 
166
184
  return nil if path.nil?
167
185
  return [] if path.empty?
@@ -201,7 +219,9 @@ module Recls
201
219
  # f7. array of all path parts, which may be empty (not nil)
202
220
  #
203
221
  # dependencies: Util.path_parts, Util.get_windows_root
204
- def self.split_path(p)
222
+ #
223
+ # @!visibility private
224
+ def self.split_path(p) # :nodoc:
205
225
 
206
226
  f1_windows_root, remainder = self.get_windows_root p
207
227
  f1_windows_root = nil if not f1_windows_root or f1_windows_root.empty?
@@ -267,14 +287,12 @@ module Recls
267
287
  # f2. A boolean indicating whether to 'consume' the basename
268
288
  #
269
289
  # dependencies: OS.is_root_dir_, OS.get_number_of_dots_dir_,
270
- def self.canonicalise_parts(parts, basename = nil)
290
+ #
291
+ # @!visibility private
292
+ def self.canonicalise_parts(parts, basename = nil) # :nodoc:
271
293
 
272
294
  newParts = []
273
295
 
274
- =begin
275
- trailing_slash = parts.empty? ? nil : self.get_trailing_slash(parts[-1])
276
- =end
277
-
278
296
  lastSingleDots = nil
279
297
 
280
298
  path_is_rooted = nil
@@ -423,18 +441,22 @@ module Recls
423
441
 
424
442
  [ newParts.join(''), consume_basename ]
425
443
  end
426
- end
444
+ end # module Util
427
445
 
428
446
  # Canonicalises a path
429
447
  #
430
448
  # Note: contains a trailing slash if, in the context of the given
431
449
  # path, the last element of the canonicalised path is a directory
432
450
  # unequivocally
433
- def self.canonicalise_path(path)
451
+ #
452
+ # @!visibility private
453
+ def self.canonicalise_path(path) # :nodoc:
434
454
 
435
455
  return nil if not path
436
456
  return '' if path.empty?
437
457
 
458
+ path = File.expand_path(path) if '~' == path[0].to_s
459
+
438
460
  f1_windows_root, f2_directory, f3_basename, dummy1, dummy2, directory_parts, dummy3 = Util.split_path(path)
439
461
 
440
462
  # suppress unused warnings
@@ -454,18 +476,58 @@ module Recls
454
476
  return "#{f1_windows_root}#{canonicalised_directory}#{f3_basename}"
455
477
  end
456
478
 
479
+ # @!visibility private
480
+ def self.absolute_path?(path) # :nodoc:
481
+
482
+ case path
483
+ when nil
484
+
485
+ return nil
486
+ when ::String
487
+
488
+ return nil if path.empty?
489
+
490
+ path = File.expand_path(path) if '~' == path[0]
491
+ when ::Recls::Entry
492
+
493
+ return path
494
+ else
495
+
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
+
499
+ f1_windows_root, f2_directory, dummy1, dummy2, dummy3, dummy4, dummy5 = Util.split_path(path)
500
+
501
+ dummy1 = dummy2 = dummy3 = dummy4 = dummy5 = nil
502
+
503
+ unless f1_windows_root
504
+
505
+ return nil unless f2_directory
506
+
507
+ return nil unless Util.is_path_name_separator(f2_directory[0])
508
+ end
509
+
510
+ Recls::Ximpl.stat_prep(path, nil, Recls::DETAILS_LATER)
511
+ end
512
+
457
513
  # determines the absolute path of a given path
458
- def self.absolute_path(path, refdir = nil)
514
+ #
515
+ # @!visibility private
516
+ def self.absolute_path(path, refdir = nil) # :nodoc:
459
517
 
460
518
  case path
461
519
  when ::NilClass
520
+
462
521
  return nil
463
522
  when ::String
523
+
524
+ path = File.expand_path(path) if '~' == path[0]
464
525
  when ::Recls::Entry
465
- path = path.to_s
526
+
527
+ return path.path
466
528
  else
467
529
 
468
- raise TypeError, "parameter path ('#{path}') is of type #{path.class} must be an instance of #{::String} or #{::Recls::Entry}"
530
+ raise TypeError, "parameter path ('#{path}') is of type #{path.class} must be an instance of #{::String} or Recls::Entry"
469
531
  end
470
532
 
471
533
  return '' if path.empty?
@@ -522,7 +584,8 @@ module Recls
522
584
  # is
523
585
  # ghi.jkl
524
586
  #
525
- def self.basename(path)
587
+ # @!visibility private
588
+ def self.basename(path) # :nodoc:
526
589
 
527
590
  return nil if not path
528
591
 
@@ -565,7 +628,9 @@ module Recls
565
628
  # ghi.jkl
566
629
  # is
567
630
  # .jkl
568
- def self.file_ext(path)
631
+ #
632
+ # @!visibility private
633
+ def self.file_ext(path) # :nodoc:
569
634
 
570
635
  return nil if not path
571
636
 
@@ -603,7 +668,8 @@ module Recls
603
668
 
604
669
  # obtains the directory from the directory path
605
670
  #
606
- def self.directory_from_directory_path(directory_path)
671
+ # @!visibility private
672
+ def self.directory_from_directory_path(directory_path) # :nodoc:
607
673
 
608
674
  wr, rem = Util.get_windows_root(directory_path)
609
675
 
@@ -614,7 +680,9 @@ module Recls
614
680
  end
615
681
 
616
682
  # obtains the directory parts from a directory
617
- def self.directory_parts_from_directory(directory)
683
+ #
684
+ # @!visibility private
685
+ def self.directory_parts_from_directory(directory) # :nodoc:
618
686
 
619
687
  return nil if not directory
620
688
 
@@ -638,7 +706,9 @@ module Recls
638
706
 
639
707
  # obtains the relative path of a given path and
640
708
  # a reference directory
641
- def self.derive_relative_path(origin, path)
709
+ #
710
+ # @!visibility private
711
+ def self.derive_relative_path(origin, path) # :nodoc:
642
712
 
643
713
  return nil if path.nil?
644
714
  return nil if path.empty?
@@ -648,10 +718,16 @@ module Recls
648
718
  path = self.canonicalise_path path
649
719
  origin = self.canonicalise_path origin
650
720
 
721
+ path = self.absolute_path path
722
+ origin = self.absolute_path origin
723
+
724
+ return path if /^\.[\\\/]*$/ =~ origin
725
+
651
726
  path_splits = Util.split_path(path)
652
727
  origin_splits = Util.split_path(origin)
653
728
 
654
729
  # if different windows root, then cannot provide relative
730
+
655
731
  if path_splits[0] and origin_splits[0]
656
732
 
657
733
  return path if path_splits[0] != origin_splits[0]
@@ -662,7 +738,7 @@ module Recls
662
738
  path_parts = path_splits[6]
663
739
  origin_parts = origin_splits[6]
664
740
 
665
- while true
741
+ loop do
666
742
 
667
743
  break if path_parts.empty?
668
744
  break if origin_parts.empty?
@@ -695,12 +771,14 @@ module Recls
695
771
  return '../' * origin_parts.size + path_parts.join('')
696
772
  end
697
773
 
698
-
699
- def self.combine_paths(paths, options)
774
+ # @!visibility private
775
+ def self.combine_paths(paths, options) # :nodoc:
700
776
 
701
777
  paths = [ paths ] unless ::Array === paths
702
778
  abs_ix = 0
703
779
 
780
+ paths = paths.map { |path| '~' == path[0].to_s ? File.expand_path(path) : path }
781
+
704
782
  paths.each_with_index do |path, index|
705
783
 
706
784
  dummy1, f2_directory, dummy2, dummy3, dummy4, dummy5, dummy6 = Util.split_path(path)
@@ -721,7 +799,7 @@ module Recls
721
799
 
722
800
  paths = paths[abs_ix..-1]
723
801
 
724
- r = File.join *paths
802
+ r = File.join(*paths)
725
803
 
726
804
  cap = options[:canonicalise] || options[:canonicalize]
727
805
 
@@ -751,7 +829,8 @@ module Recls
751
829
  # * (Mac OSX) /dev/fd/<N> - some of these stat() as directories but
752
830
  # Dir.new fails with ENOTDIR
753
831
  #
754
- def self.dir_entries_maybe(dir, flags)
832
+ # @!visibility private
833
+ def self.dir_entries_maybe(dir, flags) # :nodoc:
755
834
 
756
835
  begin
757
836
 
@@ -769,8 +848,31 @@ module Recls
769
848
  return []
770
849
  end
771
850
  end
772
- end
773
- end
851
+
852
+ # @!visibility private
853
+ def self.stat_prep(path, search_root, flags) # :nodoc:
854
+
855
+ begin
856
+
857
+ Recls::Entry.new(path, Recls::Ximpl::FileStat.stat(path), search_root, flags)
858
+ rescue Errno::ENOENT, Errno::ENXIO => x
859
+
860
+ x = x # suppress warning
861
+
862
+ if 0 != (flags & Recls::DETAILS_LATER)
863
+
864
+ Recls::Entry.new(path, nil, search_root, flags)
865
+ else
866
+
867
+ nil
868
+ end
869
+ end
870
+ end
871
+ end # module Ximpl
872
+
873
+ # :startdoc:
874
+
875
+ end # module Recls
774
876
 
775
877
  # ############################## end of file ############################# #
776
878
 
@@ -1,14 +1,14 @@
1
1
  # ######################################################################### #
2
- # File: recls/ximpl/windows.rb
2
+ # File: recls/ximpl/windows.rb
3
3
  #
4
- # Purpose: Windows-specific constructs for the recls library.
4
+ # Purpose: Windows-specific constructs for the recls library.
5
5
  #
6
- # Created: 19th February 2014
7
- # Updated: 18th June 2016
6
+ # Created: 19th February 2014
7
+ # Updated: 14th April 2019
8
8
  #
9
- # Author: Matthew Wilson
9
+ # Author: Matthew Wilson
10
10
  #
11
- # Copyright (c) 2012-2016, Matthew Wilson and Synesis Software
11
+ # Copyright (c) 2012-2019, Matthew Wilson and Synesis Software
12
12
  # All rights reserved.
13
13
  #
14
14
  # Redistribution and use in source and binary forms, with or without
@@ -38,11 +38,17 @@
38
38
 
39
39
  require 'Win32API'
40
40
 
41
- module Recls
41
+ =begin
42
+ =end
42
43
 
43
- module Ximpl
44
+ module Recls # :nodoc:
44
45
 
45
- class FileStat < File::Stat
46
+ # :stopdoc:
47
+
48
+ module Ximpl # :nodoc: all
49
+
50
+ # @!visibility private
51
+ class FileStat < File::Stat # :nodoc:
46
52
 
47
53
  private
48
54
  GetFileAttributes = Win32API.new('kernel32', 'GetFileAttributes', [ 'P' ], 'I')
@@ -70,9 +76,11 @@ module Recls
70
76
 
71
77
  BHFI_pack_string = 'LQQQLLLLLL'
72
78
 
73
- class ByHandleInformation
79
+ # @!visibility private
80
+ class ByHandleInformation # :nodoc:
74
81
 
75
- def initialize(path)
82
+ # @!visibility private
83
+ def initialize(path) # :nodoc:
76
84
 
77
85
  @volume_id = 0
78
86
  @file_index = 0
@@ -101,19 +109,24 @@ module Recls
101
109
  end
102
110
  end
103
111
 
112
+ # @!visibility private
104
113
  attr_reader :volume_id
114
+ # @!visibility private
105
115
  attr_reader :file_index
116
+ # @!visibility private
106
117
  attr_reader :num_links
107
118
  end
108
119
 
109
120
  private
110
- def has_attribute_? (attr)
121
+ # @!visibility private
122
+ def has_attribute_? (attr) # :nodoc:
111
123
 
112
124
  0 != (attr & @attributes)
113
125
  end
114
126
 
115
127
  private
116
- def initialize(path)
128
+ # @!visibility private
129
+ def initialize(path) # :nodoc:
117
130
 
118
131
  @path = path
119
132
 
@@ -121,8 +134,10 @@ module Recls
121
134
  attributes = GetFileAttributes.call("#{path}")
122
135
 
123
136
  if 0xffffffff == attributes
137
+
124
138
  @attributes = 0
125
139
  else
140
+
126
141
  @attributes = attributes
127
142
  end
128
143
 
@@ -137,62 +152,78 @@ module Recls
137
152
  end
138
153
 
139
154
  public
155
+ # @!visibility private
140
156
  attr_reader :attributes
157
+ # @!visibility private
141
158
  attr_reader :path
159
+ # @!visibility private
142
160
  attr_reader :by_handle_information
161
+ # @!visibility private
143
162
  attr_reader :short_path
144
163
 
145
- def hidden?
164
+ # @!visibility private
165
+ def hidden? # :nodoc:
146
166
 
147
167
  0 != (FILE_ATTRIBUTE_HIDDEN & @attributes)
148
168
  end
149
169
 
150
170
  # Windows-specific attributes
151
171
 
152
- def system?
172
+ # @!visibility private
173
+ def system? # :nodoc:
153
174
 
154
175
  has_attribute_? FILE_ATTRIBUTE_SYSTEM
155
176
  end
156
177
 
157
- def archive?
178
+ # @!visibility private
179
+ def archive? # :nodoc:
158
180
 
159
181
  has_attribute_? FILE_ATTRIBUTE_ARCHIVE
160
182
  end
161
183
 
162
- def device?
184
+ # @!visibility private
185
+ def device? # :nodoc:
163
186
 
164
187
  has_attribute_? FILE_ATTRIBUTE_DEVICE
165
188
  end
166
189
 
167
- def normal?
190
+ # @!visibility private
191
+ def normal? # :nodoc:
168
192
 
169
193
  has_attribute_? FILE_ATTRIBUTE_NORMAL
170
194
  end
171
195
 
172
- def temporary?
196
+ # @!visibility private
197
+ def temporary? # :nodoc:
173
198
 
174
199
  has_attribute_? FILE_ATTRIBUTE_TEMPORARY
175
200
  end
176
201
 
177
- def compressed?
202
+ # @!visibility private
203
+ def compressed? # :nodoc:
178
204
 
179
205
  has_attribute_? FILE_ATTRIBUTE_COMPRESSED
180
206
  end
181
207
 
182
- def encrypted?
208
+ # @!visibility private
209
+ def encrypted? # :nodoc:
183
210
 
184
211
  has_attribute_? FILE_ATTRIBUTE_ENCRYPTED
185
212
  end
186
213
 
187
214
 
188
215
  public
189
- def FileStat.stat(path)
216
+ # @!visibility private
217
+ def FileStat.stat(path) # :nodoc:
190
218
 
191
219
  Recls::Ximpl::FileStat.new(path)
192
220
  end
193
- end
194
- end
195
- end
221
+ end # class FileStat
222
+ end # module Ximpl
223
+
224
+ # :startdoc:
225
+
226
+ end # module Recls
196
227
 
197
228
  # ############################## end of file ############################# #
198
229