Class: Evilution::Coverage::MapStore

Inherits:
Object
  • Object
show all
Defined in:
lib/evilution/coverage/map_store.rb

Overview

Disk cache for a per-example coverage Map under .evilution/coverage/, keyed by a per-file content digest so a map survives across runs and invalidates one file at a time.

load is partial: it returns a Map pruned to the files whose on-disk content still matches the cached digest. A stale or deleted file is dropped (so its ‘built?` is false and the caller falls back to lexical targeting) while every fresh file stays queryable. A missing or corrupt cache returns nil, signalling the caller to rebuild from scratch.

Constant Summary collapse

DEFAULT_ROOT =
".evilution/coverage"
CACHE_FILE =
"map.json"

Instance Method Summary collapse

Constructor Details

#initialize(root: DEFAULT_ROOT, digest: Evilution::Coverage::Digest.new) ⇒ MapStore

Returns a new instance of MapStore.



22
23
24
25
# File 'lib/evilution/coverage/map_store.rb', line 22

def initialize(root: DEFAULT_ROOT, digest: Evilution::Coverage::Digest.new)
  @root = root
  @digest = digest
end

Instance Method Details

#load(source_files) ⇒ Object



33
34
35
36
37
38
39
40
# File 'lib/evilution/coverage/map_store.rb', line 33

def load(source_files)
  payload = read_payload
  return nil unless payload

  cached_digests = payload["digests"] || {}
  fresh = source_files.select { |file| fresh?(file, cached_digests) }
  pruned_map(payload["map"] || {}, fresh)
end

#save(map, source_files) ⇒ Object



27
28
29
30
31
# File 'lib/evilution/coverage/map_store.rb', line 27

def save(map, source_files)
  payload = { "digests" => digests_for(source_files), "map" => map.to_h }
  FileUtils.mkdir_p(@root)
  File.write(cache_path, JSON.generate(payload))
end

#stale_files(source_files) ⇒ Object

Source files whose on-disk content no longer matches the cache (changed, deleted, or never cached) – the caller rebuilds these. Every file is stale when there is no cache at all.



45
46
47
48
49
50
51
# File 'lib/evilution/coverage/map_store.rb', line 45

def stale_files(source_files)
  payload = read_payload
  return source_files.dup unless payload

  cached_digests = payload["digests"] || {}
  source_files.reject { |file| fresh?(file, cached_digests) }
end