Move asset-import staleness cache (hash/size/mtime, importer_version) out of committed .meta into .cache/
Problem
editor/types/MetaFile.zig's MetaFile mixes two very different kinds of data into the same <path>.meta file, which lives in assets/ and is git-tracked:
- Authored/durable:
guid,asset_type,import_settings,sub_assets— identity and artist-configured settings. These must be shared across the team (a stable GUID is required for scene references to resolve identically for every clone), so committing them is correct. - Pure staleness cache:
source_hash,source_size,source_mtime_ns,importer_version— exist only soAssetImporter.needsReimport/importAsset's fast path can skip rehashing an unchanged source file. Nothing reads these as "designed" data; they're fully recomputable from the source file and the current importer code.
Keeping the cache fields inside the committed file causes real problems:
- Git doesn't preserve mtime. Every fresh clone/checkout gets checkout-time mtimes, which won't match whatever a teammate's
.metalast recordedsource_mtime_nsas. The very first import after any clone is guaranteed to see a stat mismatch and rewrite the.meta— a real tracked-file diff caused purely by checking the repo out, with zero relation to any actual asset edit. - Any bug that causes a spurious
ensureMeta/writeArtifactrewrite pollutes git status for the whole team, not just the machine that triggered it, because the rewritten file is committed. We just hit exactly this: a case-sensitivity bug inAssetRegistry.lookupByFilenameclassified uppercase-extension textures (M_StatueGlass_*.TGA, common in real-world asset packs like Bistro) as.unknownforever, which madeAssetMeta.ensureMetamark them dirty and rewrite their.metaon every single scan, which the Studio hot-reload watcher (AssetWatcher.zig) then saw as an external change, re-triggeringrefreshComponents→ a full reflect compile → an endless "Compile scripts: done" toast storm and ~6 FPS on the Bistro sample. The classifier bug is fixed, but the fact that a rewrite loop in cache bookkeeping was even capable of dirtying a tracked file is the deeper issue — the next bug of this shape (e.g. #146 (closed)'s already-noted 0-byte-hash duplicate.metafrom FBX backslash paths) will have the same blast radius. - Noisy diffs/reviews. Any reimport (importer version bump during active development,
Reimport All, a differently-behaving OS/filesystem) touches every asset's committed.meta, even when the meaningful fields (guid, settings) didn't change — real diffs get buried in cache-stamp churn.
Proposed direction
Split MetaFile in two:
<path>.meta(committed, unchanged shape minus the four cache fields):guid,asset_type,import_settings,source_deps,artifact_deps,sub_assets.- A new per-project stamp store under the already-gitignored
.cache/(sibling to the existing.cache/assets/{guid}{ext}artifacts), keyed by GUID, holdingsource_hash,source_size,source_mtime_ns,importer_version. Could be one file per GUID (matches the existing artifact-file convention, avoids single-file contention) or one small index file — either is fine as an implementation detail.
Migration is naturally self-healing: since these fields are pure cache, dropping them from the MetaFile schema means old committed .meta files simply stop carrying them on next write (serde ignores/omits unknown fields), and every asset gets treated as needing a fast-path stat check once (worst case: one extra hash pass), never a correctness issue. A follow-up cleanup pass could strip the fields from existing tracked .meta files in one commit for a clean diff, but isn't required for correctness.
Acceptance
- Cloning the repo fresh and opening the project shows no
.metadiffs from import alone (only.cache/changes, which are gitignored). - Bumping an importer version (
AssetImporter.VERSION_*) or runningReimport Allno longer touches committed.metafiles unlessguid/asset_type/import_settings/sub_assetsactually changed. git statusstays clean after opening/importing an already-up-to-date project.
Related
- #146 (closed) (asset import full-hash pass on open) — same area, different axis: that issue is about when hashing runs, this one is about where the resulting staleness bookkeeping is stored. Worth fixing both, independently.