# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'singleton' require 'contrast/utils/object_share' module Contrast module Utils # Utility methods for building and caching hashes from strings class Sha256Builder include Singleton def initialize @sha256_cache = {} @gem_hash_cache = {} end # Return a list of "source" files. Ignore metadata files as well as files # in the spec, test or exe directories. Could potentially miss important # files but good enough for the time being. PATHS = '{lib,bin,ext}/**/*.{rb,c,h,c++,cpp,java,rs}' def files path if Dir.exist?(path) Dir.glob(File.join(path, PATHS)) else [] end end # Generate a SHA256 hash of the combined source code of this Gem def sha256 path return unless path return unless File.exist?(path) && !File.directory?(path) @sha256_cache[path] ||= Digest::SHA256.file(path).to_s end def build_from_spec spec name = spec.file_name.to_s cached = @gem_hash_cache[name] return cached if cached gem_path = File.join(cache_dir(spec), name) hash = sha256(gem_path) @gem_hash_cache[name] = hash hash end def cache_dir spec gems_dir = spec.gems_dir parent_dir = File.dirname(gems_dir) File.join(parent_dir, Contrast::Utils::ObjectShare::CACHE) end end end end