Module: FindClassMethods

Defined in:
lib/metadata/util/find_class_methods.rb

Constant Summary collapse

GLOB_CHARS =
'*?[{'.freeze

Class Method Summary collapse

Class Method Details

.check_file(file, glob, flags) ⇒ Object

Determine if the file returned from “find” will be used or skipped.



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/metadata/util/find_class_methods.rb', line 28

def self.check_file(file, glob, flags)
  return nil if file == @search_path

  if @search_path == File::SEPARATOR
    file.sub!(File::SEPARATOR, "")
  else
    file.sub!("#{@search_path}#{File::SEPARATOR}", "")
  end

  return nil if file == "" || !File.fnmatch(glob, file, flags)

  @specified_path ? File.join(@specified_path, file) : file
end

.dir_and_glob(glob_pattern) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns files matching glob pattern

Parameters:

  • glob_pattern (String, Regex)

    pattern to search for

Returns:

  • (String)

    paths to files found



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/metadata/util/find_class_methods.rb', line 93

def self.dir_and_glob(glob_pattern)
  stripped_path   = glob_pattern.sub(/^[a-zA-Z]:/, "")
  glob_path       = Pathname.new(stripped_path)
  @search_path    = File::SEPARATOR
  @specified_path = File::SEPARATOR

  unless glob_path.absolute?
    @search_path    = Dir.getwd
    @specified_path = nil
  end

  components   = path_components(glob_path)
  @search_path = File.expand_path(@search_path, "/")
  @fs.fileExists?(@search_path) ? File.join(components) : nil
end

.find(path, max_depth = nil) { ... } ⇒ Object

Modified version of Find.find:

  • Accepts only a single path.

  • Can be restricted by depth - optimization for glob searches.

Parameters:

  • path (String)

    starting directory of the find

  • max_depth (Integer) (defaults to: nil)

    max number of levels to decend befroelookup

Yields:

  • files found



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/metadata/util/find_class_methods.rb', line 51

def self.find(path, max_depth = nil)
  block_given? || (return enum_for(__method__, path, max_depth))

  depths = [0]
  paths  = [path.dup]

  while (file = paths.shift)
    depth = depths.shift
    yield file.dup.taint
    next if max_depth && depth + 1 > max_depth

    get_dir_entries(file).each do |f|
      f = File.join(file, f)
      paths.unshift f.untaint
      depths.unshift depth + 1
    end
  end
end

.get_dir_entries(directory) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/metadata/util/find_class_methods.rb', line 70

def self.get_dir_entries(directory)
  return [] unless @fs.fileExists?(directory) && @fs.fileDirectory?(directory)

  files = @fs.dirEntries(directory)
  files -= [".", ".."]
  files.sort!
  files.reverse_each
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
  $log.info "find: while-loop @fs.dirEntries #{directory} returned an error"
  []
end

.glob(glob_pattern, filesys, flags = 0) { ... } ⇒ Object

Return directory entries matching specified glob pattern

Parameters:

  • glob_pattern (String)

    pattern to match

  • flags (Integer) (defaults to: 0)

    file match flags

Yields:

  • block invoked with each match if specified

See Also:



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/metadata/util/find_class_methods.rb', line 12

def self.glob(glob_pattern, filesys, flags = 0)
  @fs = filesys
  return [] unless (glob = dir_and_glob(glob_pattern))

  ra = []
  find(@search_path, glob_depth(glob)) do |p|
    if (p = check_file(p, glob, flags))
      block_given? ? yield(p) : ra << p
    end
  end
  ra.sort_by(&:downcase)
end

.glob_depth(glob_pattern) ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return max levels which glob pattern may resolve to

Parameters:

  • glob_pattern (String, Regex)

    pattern to search for

Returns:

  • (Integer)

    max levels which pattern may match



127
128
129
130
131
132
# File 'lib/metadata/util/find_class_methods.rb', line 127

def self.glob_depth(glob_pattern)
  path_components = Pathname(glob_pattern).each_filename.to_a
  return nil if path_components.include?('**')

  path_components.length
end

.glob_str?(str) ⇒ Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/metadata/util/find_class_methods.rb', line 83

def self.glob_str?(str)
  str.gsub(/\\./, "X").count(GLOB_CHARS) != 0
end

.path_components(glob_path, search_path = @search_path) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/metadata/util/find_class_methods.rb', line 109

def self.path_components(glob_path, search_path = @search_path)
  components = glob_path.each_filename.to_a
  while (comp = components.shift)
    if glob_str?(comp)
      components.unshift(comp)
      break
    end
    @search_path = File.join(search_path, comp)
    @specified_path = @specified_path ? File.join(@specified_path, comp) : comp
  end
  components
end