Documentation
¶
Index ¶
- Constants
- func MarkFileComplete(versionDir, fileID string) error
- type Cache
- func (c *Cache) CloneMod(dest *Cache, gameID, sourceID, modID, version string) error
- func (c *Cache) Delete(gameID, sourceID, modID, version string) error
- func (c *Cache) Exists(gameID, sourceID, modID, version string) bool
- func (c *Cache) GetFilePath(gameID, sourceID, modID, version, relativePath string) string
- func (c *Cache) HasFileIDs(gameID, sourceID, modID, version string, fileIDs []string) bool
- func (c *Cache) ListFiles(gameID, sourceID, modID, version string) ([]string, error)
- func (c *Cache) ModPath(gameID, sourceID, modID, version string) string
- func (c *Cache) Size(gameID, sourceID, modID, version string) (int64, error)
- func (c *Cache) Store(gameID, sourceID, modID, version, relativePath string, content []byte) error
Constants ¶
const ReservedPrefix = ".lmm-"
ReservedPrefix marks lmm's own bookkeeping entries inside a cache version directory. Nothing under it is mod content: reserved entries are excluded from every enumerator of a version directory (ListFiles, Size) so they can never be deployed, counted, checksummed, or conflict-matched.
It is exported so the archive extractor (internal/core) can enforce the same namespace from the other side: mod archives are untrusted content, and a member shipped under this prefix could otherwise forge a completion marker (making the cache-first guard skip a real download) or hide itself from deploy. One constant, both sides.
Variables ¶
This section is empty.
Functions ¶
func MarkFileComplete ¶ added in v1.25.0
MarkFileComplete writes the zero-byte completion marker for fileID into versionDir, recording that this source file's content has been fully committed to that cache entry. It is the write side of HasFileIDs.
versionDir is a raw directory path rather than a cache key because the marker is written into the STAGING directory just before it is swapped into place (see internal/core/service.go's commitStagedCacheWithMarker), so the marker and the content it vouches for become visible in the same atomic rename - a marker can never appear without its content.
An unverifiable fileID (blank, or carrying a path separator - see verifiableFileID) is skipped rather than rejected: HasFileIDs refuses those same IDs, so the entry simply reads as incomplete and costs a redundant re-download, which is the safe direction and never a write outside versionDir.
Types ¶
type Cache ¶
type Cache struct {
// contains filtered or unexported fields
}
Cache manages the central mod file cache
func New ¶
New creates a new cache manager for the global cache (basePath/gameID/source-mod/version).
func NewGameScoped ¶ added in v1.1.0
NewGameScoped creates a cache for a per-game cache_path. Paths are basePath/source-mod/version (no gameID); the base is already game-specific.
func (*Cache) CloneMod ¶ added in v1.3.3
CloneMod copies a cached mod version into another cache.
Unlike every other walker it deliberately INCLUDES lmm's own .lmm-* bookkeeping entries: a clone is meant to reproduce the entry itself, not enumerate its mod content, and the reinstall cache transaction (internal/core/flows.go) round-trips a live entry through a staged/snapshot cache and back. Dropping the completion markers on that round trip would silently downgrade a complete entry to a pre-marker one and cost a redundant redownload on the next cache-first check.
func (*Cache) GetFilePath ¶
GetFilePath returns the full path to a cached file
func (*Cache) HasFileIDs ¶ added in v1.25.0
HasFileIDs reports whether every named source file has been fully committed to the given (gameID, sourceID, modID, version) cache entry - a stronger guard than Exists alone, which only checks the version directory's presence and can return true for a PARTIALLY populated entry (e.g. a previous download run that stored file 1 of 2 before failing - each file is committed to the cache individually, so a broken-off run leaves the directory present but incomplete). Callers doing a "cache already has this, skip downloading" check (see internal/core/flows.go's ApplyProfileSwitch and cmd/lmm/profile.go's doProfileApply, both #96) should use this instead of Exists to decide whether a re-download is genuinely unnecessary.
Completeness is judged by the per-file markers MarkFileComplete writes, NOT by on-disk filenames: under the default DeployExtract mode a cache version directory holds an archive's EXTRACTED MEMBERS, whose names have nothing to do with the DownloadableFile's own FileName, so a filename-based check would report false for essentially every archive-based mod and redownload despite a complete cache.
LEGACY ENTRIES: a cache directory populated before markers existed (or by `lmm import`, which writes cache entries directly) carries no markers and therefore reads as incomplete. That costs exactly one redundant redownload, which commits markers on the way through and makes every later check a hit.
An empty/nil fileIDs degrades to Exists - there is nothing left to verify beyond the directory's presence. An unverifiable ID (blank, or carrying a path separator) reports false rather than being skipped.
func (*Cache) ListFiles ¶
ListFiles returns all files in a cached mod version.
This is the choke point every consumer of a cache entry's contents goes through - Installer.Install/Replace/Undeploy, DetectConflicts, `lmm verify`'s file-count check, DownloadModResult.FilesExtracted - so lmm's own bookkeeping entries (the .lmm-* completion markers, see MarkFileComplete) are excluded here and never reach any of them. A version directory holding ONLY markers correctly reports zero files.
CloneMod is the sole exception and walks with includeReserved - see there.