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