class Bundler::Checksum::Store
def fetch_checksum(lock_name, algo)
def fetch_checksum(lock_name, algo) @store[lock_name]&.fetch(algo, nil) end
def initialize
def initialize @store = {} @store_mutex = Mutex.new end
def inspect
def inspect "#<#{self.class}:#{object_id} size=#{store.size}>" end
def merge!(other)
def merge!(other) other.store.each do |lock_name, checksums| checksums.each do |_algo, checksum| register_checksum(lock_name, checksum) end end end
def merge_checksum(lock_name, checksum, existing)
def merge_checksum(lock_name, checksum, existing) existing.merge!(checksum) || raise(ChecksumMismatchError.new(lock_name, existing, checksum)) end
def register(spec, checksum)
def register(spec, checksum) return unless checksum register_checksum(spec.name_tuple.lock_name, checksum) end
def register_checksum(lock_name, checksum)
def register_checksum(lock_name, checksum) @store_mutex.synchronize do existing = fetch_checksum(lock_name, checksum.algo) if existing merge_checksum(lock_name, checksum, existing) else store_checksum(lock_name, checksum) end end end
def replace(spec, checksum)
This ensures a mismatch error where there are multiple top level sources
However, if the new checksum is from a different source, we register like normal.
In the Index, the later gem replaces the former, so we do that here.
"darwin20" and "darwin-20", both of which resolve to darwin-20.
In particular, this is when 2 gems have two similar platforms, e.g.
duplicates of the same gem (according to full_name) in the index.
The primary purpose is registering checksums from gems where there are
Replace when the new checksum is from the same source.
def replace(spec, checksum) return unless checksum lock_name = spec.name_tuple.lock_name @store_mutex.synchronize do existing = fetch_checksum(lock_name, checksum.algo) if !existing || existing.same_source?(checksum) store_checksum(lock_name, checksum) else merge_checksum(lock_name, checksum, existing) end end end
def store_checksum(lock_name, checksum)
def store_checksum(lock_name, checksum) (@store[lock_name] ||= {})[checksum.algo] = checksum end
def to_lock(spec)
def to_lock(spec) lock_name = spec.name_tuple.lock_name checksums = @store[lock_name] if checksums "#{lock_name} #{checksums.values.map(&:to_lock).sort.join(",")}" else lock_name end end