# frozen_string_literal: true module Picopackage module Scanner Found = Struct.new(:path, :package) # Scanning walks whole trees, so it has to survive binaries, unreadable # files and anything large enough that reading it to look for a comment # would be silly. MAX_SCAN_SIZE = 1024 * 1024 def self.scan(directory, pattern: "**/*") Dir.glob(File.join(directory, pattern)).sort.filter_map do |path| content = readable_text(path) next unless content&.match?(METADATA_PATTERN) Found.new(path, Package.new(content: content)) end end def self.readable_text(path) return nil unless File.file?(path) return nil if File.size(path) > MAX_SCAN_SIZE content = File.read(path, encoding: "UTF-8") content.valid_encoding? ? content : nil rescue SystemCallError, ArgumentError nil end end end