···
12
+
"github.com/dgraph-io/ristretto"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"tangled.sh/tangled.sh/core/patchutil"
18
+
type MergeCheckCache struct {
19
+
cache *ristretto.Cache
23
+
mergeCheckCache MergeCheckCache
27
+
cache, _ := ristretto.NewCache(&ristretto.Config{
31
+
TtlTickerDurationInSec: 60 * 60 * 24 * 2, // 2 days
33
+
mergeCheckCache = MergeCheckCache{cache}
36
+
func (m *MergeCheckCache) cacheKey(g *GitRepo, patch []byte, targetBranch string) string {
38
+
hash := sha256.Sum256(fmt.Append([]byte{}, g.path, sep, g.h.String(), sep, patch, sep, targetBranch))
39
+
return fmt.Sprintf("%x", hash)
42
+
// we can't cache "mergeable" in risetto, nil is not cacheable
44
+
// we use the sentinel value instead
45
+
func (m *MergeCheckCache) cacheVal(check error) any {
53
+
func (m *MergeCheckCache) Set(g *GitRepo, patch []byte, targetBranch string, mergeCheck error) {
54
+
key := m.cacheKey(g, patch, targetBranch)
55
+
val := m.cacheVal(mergeCheck)
56
+
m.cache.Set(key, val, 0)
59
+
func (m *MergeCheckCache) Get(g *GitRepo, patch []byte, targetBranch string) (error, bool) {
60
+
key := m.cacheKey(g, patch, targetBranch)
61
+
if val, ok := m.cache.Get(key); ok {
62
+
if val == struct{}{} {
63
+
// cache hit for mergeable
65
+
} else if e, ok := val.(error); ok {
66
+
// cache hit for merge conflict
···
func (g *GitRepo) MergeCheck(patchData []byte, targetBranch string) error {
227
+
if val, ok := mergeCheckCache.Get(g, patchData, targetBranch); ok {
opts.FormatPatch = patchutil.IsFormatPatch(string(patchData))
···
defer os.RemoveAll(tmpDir)
189
-
return g.applyPatch(tmpDir, patchFile, true, &opts)
252
+
result := g.applyPatch(tmpDir, patchFile, true, &opts)
253
+
mergeCheckCache.Set(g, patchData, targetBranch, result)
func (g *GitRepo) Merge(patchData []byte, targetBranch string) error {