unarr/internal/library/cache.go
Deivid Soto 5a7449b9e6 chore: rename module from torrentclaw-cli to unarr
- Rename Go module path github.com/torrentclaw/torrentclaw-cli → github.com/torrentclaw/unarr
- Update all imports, ldflags, scripts, docs, and Docker config
- Add GitHub Actions release workflow (goreleaser on tag push)
2026-03-30 13:06:07 +02:00

86 lines
2 KiB
Go

package library
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/torrentclaw/unarr/internal/config"
)
// CachePath returns the default library cache file path.
func CachePath() string {
return filepath.Join(config.DataDir(), "library.json")
}
// LoadCache reads the library cache from disk. Returns nil if file doesn't exist.
func LoadCache() (*LibraryCache, error) {
return LoadCacheFrom(CachePath())
}
// LoadCacheFrom reads the library cache from a specific path.
func LoadCacheFrom(path string) (*LibraryCache, error) {
data, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("read cache: %w", err)
}
var cache LibraryCache
if err := json.Unmarshal(data, &cache); err != nil {
return nil, fmt.Errorf("parse cache: %w", err)
}
if cache.Version != cacheVersion {
return nil, nil // incompatible version, treat as missing
}
return &cache, nil
}
// SaveCache writes the library cache to disk atomically.
func SaveCache(cache *LibraryCache) error {
return SaveCacheTo(cache, CachePath())
}
// SaveCacheTo writes the library cache to a specific path atomically.
func SaveCacheTo(cache *LibraryCache, path string) error {
cache.Version = cacheVersion
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0o755); err != nil {
return fmt.Errorf("create cache dir: %w", err)
}
data, err := json.MarshalIndent(cache, "", " ")
if err != nil {
return fmt.Errorf("encode cache: %w", err)
}
tmpPath := path + ".tmp"
if err := os.WriteFile(tmpPath, data, 0o644); err != nil {
return fmt.Errorf("write temp cache: %w", err)
}
if err := os.Rename(tmpPath, path); err != nil {
os.Remove(tmpPath)
return fmt.Errorf("rename cache: %w", err)
}
return nil
}
// BuildCacheIndex creates a lookup map from filePath → index for incremental scanning.
func BuildCacheIndex(cache *LibraryCache) map[string]int {
if cache == nil {
return nil
}
idx := make(map[string]int, len(cache.Items))
for i, item := range cache.Items {
idx[item.FilePath] = i
}
return idx
}