diff options
Diffstat (limited to 'cache')
| -rw-r--r-- | cache/cache.go | 113 | ||||
| -rw-r--r-- | cache/cache_test.go | 79 |
2 files changed, 192 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) +} diff --git a/cache/cache_test.go b/cache/cache_test.go new file mode 100644 index 0000000..fa81974 --- /dev/null +++ b/cache/cache_test.go @@ -0,0 +1,79 @@ +package cache + +import ( + "github.com/stretchr/testify/assert" + "strings" + "testing" +) + +func TestFromReader_Blank(t *testing.T) { + input := ` +` + sr := strings.NewReader(input) + c, err := FromReader(sr) + assert.Nil(t, err) + assert.Len(t, c.Entries, 0) +} + +func TestFromReader_OneEntry(t *testing.T) { + input := `/abc/def # deffers` + sr := strings.NewReader(input) + c, err := FromReader(sr) + assert.Nil(t, err) + assert.Len(t, c.Entries, 1) + assert.Equal(t, c.Entries[0], Entry{ + Path: "/abc/def", + Label: "deffers", + }) +} + +func TestFromReader_ManyEntries(t *testing.T) { + input := `/abc/def # deffers +/123/aa # i love aa +/path/src # da source +` + sr := strings.NewReader(input) + c, err := FromReader(sr) + assert.Nil(t, err) + assert.Len(t, c.Entries, 3) + assert.Equal(t, c.Entries[0], Entry{ + Path: "/abc/def", + Label: "deffers", + }) + assert.Equal(t, c.Entries[1], Entry{ + Path: "/123/aa", + Label: "i love aa", + }) + assert.Equal(t, c.Entries[2], Entry{ + Path: "/path/src", + Label: "da source", + }) +} + +func TestFromReader_Comments(t *testing.T) { + input := ` +// comment +/abc/def # deffers +# comment +/123/aa # i love aa +// # comment +/path/src # da source +# // comment +` + sr := strings.NewReader(input) + c, err := FromReader(sr) + assert.Nil(t, err) + assert.Len(t, c.Entries, 3) + assert.Equal(t, c.Entries[0], Entry{ + Path: "/abc/def", + Label: "deffers", + }) + assert.Equal(t, c.Entries[1], Entry{ + Path: "/123/aa", + Label: "i love aa", + }) + assert.Equal(t, c.Entries[2], Entry{ + Path: "/path/src", + Label: "da source", + }) +} |
