lib/spandx/core/cache.rb in spandx-0.12.3 vs lib/spandx/core/cache.rb in spandx-0.13.0

- old
+ new

@@ -1,86 +1,73 @@ # frozen_string_literal: true module Spandx module Core class Cache - attr_reader :db, :package_manager + include Enumerable - def initialize(package_manager, db: Spandx.git[:cache]) - @package_manager = package_manager - @db = db - @cache = {} - @lines = {} + attr_reader :package_manager, :root + + def initialize(package_manager, root:) + @package_manager = package_manager.to_s + @root = root end def licenses_for(name, version) - found = search(name: name, version: version) - Spandx.logger.debug("Cache miss: #{name}-#{version}") if found.nil? + return [] if name.nil? || name.empty? + + found = datafile_for(name).search(name: name, version: version) + Spandx.logger.debug { "Cache miss: #{name}-#{version}" } unless found found ? found[2].split('-|-') : [] end - private - - def digest_for(components) - Digest::SHA1.hexdigest(Array(components).join('/')) + def each + datafiles.each do |_hex, datafile| + datafile.each do |item| + yield item + end + end end - def key_for(name) - digest_for(name)[0...2] + def insert(name, version, licenses) + return if name.nil? || name.empty? + + datafile_for(name).insert(name, version, licenses) end - def search(name:, version:) - datafile = datafile_for(name) - db.open(datafile) do |io| - search_for("#{name}-#{version}", io, @lines.fetch(datafile) { |key| @lines[key] = lines_in(io) }) - end - rescue Errno::ENOENT => error - Spandx.logger.error(error) - nil + def insert!(*args) + insert(*args) + rebuild_index end def datafile_for(name) - ".index/#{key_for(name)}/#{package_manager}" + datafiles.fetch(key_for(name)) end - def lines_in(io) - lines = [] - io.seek(0) - until io.eof? - lines << io.pos - io.gets + def rebuild_index + datafiles.each do |_hex, datafile| + datafile.index.update! end - lines end - def search_for(term, io, lines) - return if lines.empty? - return @cache[term] if @cache.key?(term) + private - mid = lines.size == 1 ? 0 : lines.size / 2 - io.seek(lines[mid]) - comparison = matches?(term, parse_row(io)) do |row| - return row - end + def digest_for(name) + Digest::SHA1.hexdigest(name) + end - search_for(term, io, partition(comparison, mid, lines)) + def key_for(name) + digest_for(name)[0...2] end - def matches?(term, row) - (term <=> "#{row[0]}-#{row[1]}").tap do |comparison| - yield row if comparison.zero? + def datafiles + @datafiles ||= candidate_keys.each_with_object({}) do |key, memo| + memo[key] = DataFile.new(File.join(root, key, package_manager)) end end - def partition(comparison, mid, lines) - min, max = comparison.positive? ? [mid + 1, lines.length] : [0, mid] - lines.slice(min, max) - end - - def parse_row(io) - row = CSV.parse(io.readline)[0] - @cache["#{row[0]}-#{row[1]}"] = row - row + def candidate_keys + (0x00..0xFF).map { |x| x.to_s(16).upcase.rjust(2, '0').downcase } end end end end