Documentation
¶
Index ¶
- Constants
- func MarkFileComplete(versionDir, fileID string) error
- func MarkFileCompleteWithMembers(versionDir, fileID string, members []string) error
- func VerifiableFileID(fileID string) bool
- 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) FileManifests(gameID, sourceID, modID, version string) (map[string]FileManifest, error)
- 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
- type FileManifest
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.
A bare (zero-byte) marker vouches for completion but records no member manifest - FileManifests reports it as Recorded=false. Production commits go through MarkFileCompleteWithMembers instead; this remains the legacy shape every pre-manifest cache entry already has on disk.
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.
func MarkFileCompleteWithMembers ¶ added in v1.27.0
MarkFileCompleteWithMembers is MarkFileComplete plus provenance: the marker body records WHICH versionDir-relative members this file ID contributed (slash-separated, one per line, under the manifestHeader line), so the same-version update path can later undeploy members owned solely by a superseded file (#144 item 4). Read back via FileManifests.
A member name a line-oriented body cannot represent faithfully (embedded newline/carriage return) degrades the WHOLE write to a bare legacy marker: completion is still vouched for, but no manifest is recorded, so consumers fall back to today's union behavior rather than ever trusting a corrupted member list.
func VerifiableFileID ¶ added in v1.27.0
VerifiableFileID reports whether a source file ID can be round-tripped through a marker filename. A blank ID has nothing to name, and one carrying a path separator would place (or look for) the marker outside the version directory entirely. Both are refused rather than sanitized: two distinct IDs sanitizing to the same marker would let one file's completion vouch for another's.
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) FileManifests ¶ added in v1.27.0
func (c *Cache) FileManifests(gameID, sourceID, modID, version string) (map[string]FileManifest, error)
FileManifests reads every completion marker in the version directory and returns each file ID's manifest. A directory (or entry) with no markers returns an empty map, never an error. A marker whose body is empty or carries an unrecognized header parses as Recorded=false - the safe, union-fallback direction - so pre-manifest entries and any future format revision both degrade silently rather than misreport provenance.
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 an `lmm import` that could not resolve the archive against its source's file listing - source-linked imports that do resolve stamp the marker at import time, #139) 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.
type FileManifest ¶ added in v1.27.0
type FileManifest struct {
// Members holds the version-dir-relative paths (OS separators) this file
// ID contributed to the cache entry. Meaningful only when Recorded.
Members []string
// Recorded is false for a legacy bare marker: the file's completion is
// vouched for, but WHICH members it contributed was never written down.
// Consumers must treat that as unknown provenance - never as "none".
Recorded bool
}
FileManifest is one completion marker's recorded member manifest.