Module

cache.build_cache.file_tracking

File tracking mixin for BuildCache.

Provides methods for tracking file changes, hashing, and dependency management. Used as a mixin by the main BuildCache class.

Key Concepts:

  • File fingerprints: mtime + size for fast change detection
  • SHA256 hashing: Reliable content change detection
  • Dependency tracking: Template, partial, and data file dependencies
  • Output tracking: Source → output file mapping for cleanup

Related Modules:

  • bengal.cache.build_cache.core: Main BuildCache class
  • bengal.orchestration.incremental: Incremental build logic

Classes

FileTrackingMixin
Mixin providing file tracking, hashing, and dependency management. Requires these attributes on th…
8

Mixin providing file tracking, hashing, and dependency management.

Requires these attributes on the host class:

  • file_hashes: dict[str, str]
  • file_fingerprints: dict[str, dict[str, Any]]
  • dependencies: dict[str, set[str]]
  • output_sources: dict[str, str]

Attributes

Name Type Description
file_hashes dict[str, str]
file_fingerprints dict[str, dict[str, Any]]
dependencies dict[str, set[str]]
output_sources dict[str, str]

Methods 8

hash_file
Generate SHA256 hash of a file. Delegates to centralized hash_file utility for…
1 str
def hash_file(self, file_path: Path) -> str

Generate SHA256 hash of a file.

Delegates to centralized hash_file utility for consistent behavior.

Parameters 1
file_path Path

Path to file

Returns

str

Hex string of SHA256 hash

should_bypass
Determine if cache should be bypassed for a source file. This is the single so…
2 bool
def should_bypass(self, source_path: Path, changed_sources: set[Path] | None = None) -> bool

Determine if cache should be bypassed for a source file.

This is the single source of truth for cache bypass decisions (RFC: rfc-incremental-hot-reload-invariants).

Cache bypass is required when:

  1. File is in the changed_sources set (explicit change from file watcher)
  2. File hash differs from cached hash (is_changed check)
Parameters 2
source_path Path

Path to source file

changed_sources set[Path] | None

Set of paths explicitly marked as changed (from file watcher)

Returns

bool

True if cache should be bypassed, False if cache can be used

is_changed
Check if a file has changed since last build. Performance Optimization (RFC: o…
1 bool
def is_changed(self, file_path: Path) -> bool

Check if a file has changed since last build.

Performance Optimization (RFC: orchestrator-performance-improvements):

  • Fast path: mtime + size check (single stat call, no file read)
  • Slow path: SHA256 hash only when mtime/size mismatch detected
  • Handles edge cases: touch/rsync may change mtime but not content
Parameters 1
file_path Path

Path to file

Returns

bool

True if file is new or has changed, False if unchanged

update_file
Update the fingerprint for a file (mtime + size + hash). Performance Optimizat…
1 None
def update_file(self, file_path: Path) -> None

Update the fingerprint for a file (mtime + size + hash).

Performance Optimization:

Stores full fingerprint for fast change detection on subsequent builds.
Uses mtime + size for fast path, hash for verification.
Parameters 1
file_path Path

Path to file

track_output
Track the relationship between a source file and its output file. This enables…
3 None
def track_output(self, source_path: Path, output_path: Path, output_dir: Path) -> None

Track the relationship between a source file and its output file.

This enables cleanup of output files when source files are deleted.

Parameters 3
source_path Path

Path to source file (e.g., content/blog/post.md)

output_path Path

Absolute path to output file (e.g., /path/to/public/blog/post/index.html)

output_dir Path

Site output directory (e.g., /path/to/public)

add_dependency
Record that a source file depends on another file.
2 None
def add_dependency(self, source: Path, dependency: Path) -> None

Record that a source file depends on another file.

Parameters 2
source Path

Source file (e.g., content page)

dependency Path

Dependency file (e.g., template, partial, config)

get_affected_pages
Find all pages that depend on a changed file.
1 set[str]
def get_affected_pages(self, changed_file: Path) -> set[str]

Find all pages that depend on a changed file.

Parameters 1
changed_file Path

File that changed

Returns

set[str]

Set of page paths that need to be rebuilt

invalidate_file
Remove a file from the cache (useful when file is deleted). Note: This is a pa…
1 None
def invalidate_file(self, file_path: Path) -> None

Remove a file from the cache (useful when file is deleted).

Note: This is a partial invalidation. Full invalidation of related caches (parsed_content, rendered_output, etc.) should be handled by the main BuildCache class.

Parameters 1
file_path Path

Path to file