gittuf/internal/cache/policy.go
Aditya Sirish 90a4d1a806
gittuf,cache,policy,cmd: Use persistent cache
This commit adds support for persistent cache searching as well as
explicit populating.

Signed-off-by: Aditya Sirish <aditya@saky.in>
2025-01-08 12:42:13 -05:00

129 lines
4.5 KiB
Go

// Copyright The gittuf Authors
// SPDX-License-Identifier: Apache-2.0
package cache
import (
"fmt"
"log/slog"
"slices"
"github.com/gittuf/gittuf/internal/gitinterface"
)
func (p *Persistent) GetPolicyEntries() []RSLEntryIndex {
return p.PolicyEntries
}
func (p *Persistent) HasPolicyEntryNumber(entryNumber uint64) (gitinterface.Hash, bool) {
if len(p.PolicyEntries) == 0 || entryNumber == 0 {
return gitinterface.ZeroHash, false
}
index, has := slices.BinarySearchFunc(p.PolicyEntries, RSLEntryIndex{EntryNumber: entryNumber}, binarySearch)
if !has {
return gitinterface.ZeroHash, false
}
// Unlike Find... we're actively checking if a policy number has been
// inserted into the cache before, so we return the ID from that index
// exactly
return p.PolicyEntries[index].GetEntryID(), true
}
func (p *Persistent) FindPolicyEntryNumberForEntry(entryNumber uint64) RSLEntryIndex {
if len(p.PolicyEntries) == 0 {
return RSLEntryIndex{EntryNumber: 0} // this is a special case
}
slog.Debug(fmt.Sprintf("Finding policy entry in cache before entry %d...", entryNumber))
index, has := slices.BinarySearchFunc(p.PolicyEntries, RSLEntryIndex{EntryNumber: entryNumber}, binarySearch)
if has {
// The entry number given to us is the first entry which happens
// to be the start of verification as well
// This can happen for full verification
return p.PolicyEntries[index]
}
if !has && index == 0 {
// this happens when a policy entry doesn't exist before the specified
// entryNumber
return RSLEntryIndex{EntryNumber: 0}
}
// When !has, index is point of insertion, but we want the applicable
// entry which is index-1
return p.PolicyEntries[index-1]
}
func (p *Persistent) FindPolicyEntriesInRange(firstNumber, lastNumber uint64) ([]RSLEntryIndex, error) {
if len(p.PolicyEntries) == 0 {
return nil, ErrNoPersistentCache // TODO: check if custom error makes sense
}
firstIndex, has := slices.BinarySearchFunc(p.PolicyEntries, RSLEntryIndex{EntryNumber: firstNumber}, binarySearch)
if !has {
// When !has, index is point of insertion, but we want the applicable
// entry which is index-1
firstIndex--
}
lastIndex, has := slices.BinarySearchFunc(p.PolicyEntries, RSLEntryIndex{EntryNumber: lastNumber}, binarySearch)
if has {
// When has, lastIndex is an entry we want to return, so we increment
// lastIndex to ensure the corresponding entry is included in the return
lastIndex++
}
return p.PolicyEntries[firstIndex:lastIndex], nil
}
func (p *Persistent) InsertPolicyEntryNumber(entryNumber uint64, entryID gitinterface.Hash) {
if entryNumber == 0 {
// For now, we don't have a way to track non-numbered entries
// We likely never want to track non-numbered entries in this
// cache as this is very dependent on numbering
return
}
// TODO: check this is for the right ref?
slog.Debug(fmt.Sprintf("Inserting policy entry with ID '%s' and number %d into persistent cache...", entryID.String(), entryNumber))
if len(p.PolicyEntries) == 0 {
// No entries yet, just add the current entry
slog.Debug("No policy entries in cache, adding current entry as sole item...")
p.PolicyEntries = []RSLEntryIndex{{EntryNumber: entryNumber, EntryID: entryID.String()}}
return
}
if p.PolicyEntries[len(p.PolicyEntries)-1].GetEntryNumber() < entryNumber {
// Current entry clearly belongs at the very end
slog.Debug("Current entry belongs at the end of ordered list of attestations entry, appending...")
p.PolicyEntries = append(p.PolicyEntries, RSLEntryIndex{EntryNumber: entryNumber, EntryID: entryID.String()})
return
}
// We don't check the converse where the current entry is less than the
// first entry because we're inserting as entries are encountered
// chronologically. Worst case, binary search fallthrough below will still
// handle it
slog.Debug("Searching for insertion point...")
index, has := slices.BinarySearchFunc(p.PolicyEntries, RSLEntryIndex{EntryNumber: entryNumber}, binarySearch)
if has {
// We could assume that if we've seen an entry with a number greater
// than this, we should have seen this one too, but for now...
slog.Debug("Entry with same number found, skipping addition of entry...")
return
}
slog.Debug(fmt.Sprintf("Found insertion point %d", index))
newSlice := make([]RSLEntryIndex, 0, len(p.PolicyEntries)+1)
newSlice = append(newSlice, p.PolicyEntries[:index]...)
newSlice = append(newSlice, RSLEntryIndex{EntryNumber: entryNumber, EntryID: entryID.String()})
newSlice = append(newSlice, p.PolicyEntries[index:]...)
p.PolicyEntries = newSlice
}