GitRoot

craft your forge, build your project, grow your community freely
  1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
  2//
  3// SPDX-License-Identifier: EUPL-1.2
  4
  5package main
  6
  7import (
  8	"bytes"
  9	"errors"
 10	"fmt"
 11	"io/fs"
 12	"slices"
 13	"strings"
 14)
 15
 16type CacheLine struct {
 17	fp      string
 18	toPath  string
 19	title   string
 20	selects []string
 21}
 22
 23func (p *Plugin) extractCacheLines(fp string) ([]CacheLine, []CacheLine) {
 24	res := []CacheLine{}
 25	toDelete := []CacheLine{}
 26	for _, conf := range p.config {
 27		if conf.glob.Match(fp) {
 28			content, err := fs.ReadFile(p.server.Worktree(), fp)
 29			if err != nil {
 30				p.server.Log("extractCacheLines ReadFile " + fp + " == " + err.Error())
 31				continue
 32			}
 33			if bytes.Contains(content, []byte(conf.Where)) {
 34				res = append(res, p.extractCacheLine(fp, conf, content))
 35			} else {
 36				toDelete = append(toDelete, CacheLine{fp: fp, toPath: conf.To})
 37			}
 38		}
 39	}
 40	return res, toDelete
 41}
 42func (p *Plugin) extractCacheLine(fp string, c conf, content []byte) CacheLine {
 43	res := CacheLine{
 44		fp:      fp,
 45		toPath:  c.To,
 46		title:   findTitle(fp, content),
 47		selects: make([]string, 0),
 48	}
 49	for _, selection := range c.selections {
 50		t := selection.FindSubmatch(content)
 51		if len(t) > 1 {
 52			toAppend := ""
 53			for _, a := range t[1:] {
 54				if toAppend == "" {
 55					toAppend = string(a)
 56				} else {
 57					toAppend = fmt.Sprintf("%s %s", toAppend, a)
 58				}
 59			}
 60			res.selects = append(res.selects, toAppend)
 61		} else {
 62			res.selects = append(res.selects, " ")
 63		}
 64	}
 65	return res
 66}
 67
 68func (c CacheLine) Marshal() string {
 69	return fmt.Sprintf("%s||%s||%s||%s", c.fp, c.toPath, c.title, strings.Join(c.selects, ";;"))
 70}
 71
 72func Unmarshal(s string) CacheLine {
 73	data := strings.Split(s, "||")
 74	return CacheLine{
 75		fp:      data[0],
 76		toPath:  data[1],
 77		title:   data[2],
 78		selects: slices.DeleteFunc(strings.Split(data[3], ";;"), func(s string) bool { return s == "" }),
 79	}
 80}
 81
 82func (p *Plugin) fromCache() []CacheLine {
 83	cache, err := fs.ReadFile(p.server.Cache(), cachePath)
 84	if err != nil && errors.Is(err, fs.ErrNotExist) {
 85		p.server.Log("cache not existing")
 86		return []CacheLine{}
 87	} else if err != nil {
 88		p.server.LogError("can't read cache in fromCache", err)
 89	}
 90	res := []CacheLine{}
 91	for _, line := range bytes.Split(cache, []byte("\n")) {
 92		if len(line) > 0 {
 93			res = append(res, Unmarshal(string(line)))
 94		}
 95	}
 96	return res
 97}
 98
 99func (p *Plugin) toCache() string {
100	var buf bytes.Buffer
101	for _, cl := range p.cache {
102		buf.WriteString(cl.Marshal())
103		buf.WriteString("\n")
104	}
105	return buf.String()
106}
107
108func (p *Plugin) deleteInCache(fp string) {
109	res := make([]CacheLine, 0)
110	for _, cl := range p.cache {
111		if cl.fp != fp {
112			res = append(res, cl)
113		}
114	}
115	p.cache = res
116}
117
118func (p *Plugin) deleteInCacheConf(cacheLine CacheLine) {
119	res := make([]CacheLine, 0)
120	for _, cl := range p.cache {
121		if cl.fp != cacheLine.fp || cl.toPath != cacheLine.toPath {
122			res = append(res, cl)
123		}
124	}
125	p.cache = res
126}
127
128func (p *Plugin) appendInCache(cacheLine CacheLine) {
129	found := false // check if not already stored, in case inactive/active and wortree pass
130	for _, cl := range p.cache {
131		if cl.fp == cacheLine.fp && cl.toPath == cacheLine.toPath {
132			found = true
133			break
134		}
135	}
136	p.server.Log(fmt.Sprintf("fp %s is found %t with %s", cacheLine.fp, found, cacheLine.Marshal()))
137	if !found {
138		p.cache = append(p.cache, cacheLine)
139	} else {
140		p.modifyInCache(cacheLine.fp, cacheLine)
141	}
142}
143
144func (p *Plugin) modifyInCache(oldFp string, cacheLine CacheLine) {
145	res := make([]CacheLine, len(p.cache))
146	for i, cl := range p.cache {
147		if cl.fp == oldFp && cl.toPath == cacheLine.toPath {
148			res[i] = cacheLine
149		} else {
150			res[i] = cl
151		}
152	}
153	p.cache = res
154}