class Utils::Find::ConfigurableFinder
def add_file(path, file)
def add_file(path, file) @files[path] = file self end
def close_files
def close_files @files.each_value do |f| f.closed? or f.close end nil end
def find(*paths, &block)
def find(*paths, &block) block_given? or return enum_for(__method__, *paths) paths.map! do |d| File.exist?(d) or raise Errno::ENOENT d.dup end while file = paths.shift catch(:prune) do file = prepare_file(file) visit_file?(file) and yield file begin s = stat(file) or next rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG next end if s.directory? then begin tried = false fs = Dir.entries(file) rescue Errno::EMFILE tried and raise close_files tried = true retry rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG next end fs.sort! fs.reverse_each do |f| next if f == "." or f == ".." f = File.join(file, f) paths.unshift f.untaint end end end end end
def get_file(path)
def get_file(path) @files[path] end
def include_suffix?(suffix)
def include_suffix?(suffix) @suffix.nil? || @suffix.include?(suffix) end
def initialize(opts = {})
def initialize(opts = {}) @files = {} opts[:suffix].full? { |s| @suffix = [*s] } @follow_symlinks = opts.fetch(:follow_symlinks, false) end
def prepare_file(file)
def prepare_file(file) path = file.dup.taint path.extend PathExtension path.finder = self path end
def stat(file)
def stat(file) @follow_symlinks ? file.stat : file.lstat end
def visit_file?(file)
def visit_file?(file) suffix = File.extname(file).full?(:[], 1..-1) || '' include_suffix?(suffix) end