diff options
Diffstat (limited to 'cache/cache.go')
| -rw-r--r-- | cache/cache.go | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/cache/cache.go b/cache/cache.go new file mode 100644 index 0000000..b57d8b8 --- /dev/null +++ b/cache/cache.go @@ -0,0 +1,113 @@ +package cache + +import ( + "bufio" + "errors" + "io" + "io/fs" + "os" + "path" + "pik/model" + "pik/paths" + "strings" +) + +type Cache struct { + Entries []Entry +} + +func (c Cache) Merge(other Cache) Cache { + mp := make(map[string]string) + for _, e := range append(c.Entries, other.Entries...) { + mp[e.Path] = e.Label + } + result := Cache{} + for p, l := range mp { + result.Entries = append(result.Entries, Entry{Label: l, Path: p}) + } + return result +} + +type Entry struct { + Path string + Label string +} + +var Path = path.Join(paths.Cache, "contexts") + +var UnexpectedEntryError = errors.New("unexpected cache entry") + +func Load() (Cache, error) { + fd, err := os.Open(Path) + if errors.Is(err, os.ErrNotExist) { + return Cache{}, nil + } else if err != nil { + return Cache{}, err + } + defer fd.Close() + return FromReader(fd) +} + +func FromReader(r io.Reader) (Cache, error) { + c := Cache{} + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" || line[0] == '#' || line[0:2] == "//" { + continue + } + + entry := &Entry{} + parts := strings.SplitN(line, "#", 2) + switch len(parts) { + case 2: + entry.Label = strings.TrimSpace(parts[1]) + fallthrough + case 1: + entry.Path = strings.TrimSpace(parts[0]) + default: + return c, UnexpectedEntryError + } + c.Entries = append(c.Entries, *entry) + } + return c, nil +} + +func (c Cache) String() string { + b := strings.Builder{} + for _, e := range c.Entries { + b.WriteString(e.Path) + b.WriteString(" # ") + b.WriteString(e.Label) + b.WriteString("\n") + } + return b.String() +} + +func New(st *model.State) Cache { + c := &Cache{} + for _, s := range st.Sources { + c.Entries = append(c.Entries, Entry{ + Path: s.Path, + Label: s.Label(), + }) + } + return *c +} + +func Save(s *model.State) error { + ld, err := Load() + if err != nil { + return err + } + c := New(s).Merge(ld) + return os.WriteFile(Path, []byte(c.String()), os.ModePerm) +} + +func LoadState(f fs.FS, cache Cache, indexers []model.Indexer, runners []model.Runner) (*model.State, error) { + var locs []string + for _, e := range cache.Entries { + locs = append(locs, e.Path) + } + return model.NewState(f, locs, indexers, runners) +} |
