Files
Fabric/plugins/db/fsdb/patterns.go
Matt Joyce 1f07ea25a2 refactor: unify pattern loading and variable handling
- Stronger separation of concerns between chatter.go and patterns.go
- Consolidate pattern loading logic into GetPattern method
- Support both file and database patterns through single interface
- Maintain API compatibility with Storage interface
- Handle variable substitution in one place
- Keep backward compatibility for REST API through Get method

The changes enable cleaner pattern handling while maintaining
existing interfaces and adding file-based pattern support.
2024-11-19 10:31:06 +11:00

117 lines
3.0 KiB
Go

package fsdb
import (
"fmt"
"os"
"path/filepath"
"strings"
)
type PatternsEntity struct {
*StorageEntity
SystemPatternFile string
UniquePatternsFilePath string
}
// Pattern represents a single pattern with its metadata
type Pattern struct {
Name string
Description string
Pattern string
}
// main entry point for getting patterns from any source
func (o *PatternsEntity) GetApplyVariables(source string, variables map[string]string) (*Pattern, error) {
var pattern *Pattern
var err error
// Determine if this is a file path
isFilePath := strings.HasPrefix(source, "\\") ||
strings.HasPrefix(source, "/") ||
strings.HasPrefix(source, "~") ||
strings.HasPrefix(source, ".")
if isFilePath {
pattern, err = o.getFromFile(source)
} else {
pattern, err = o.getFromDB(source)
}
if err != nil {
return nil, err
}
return o.applyVariables(pattern, variables), nil
}
// handles all variable substitution
func (o *PatternsEntity) applyVariables(pattern *Pattern, variables map[string]string) *Pattern {
if variables != nil && len(variables) > 0 {
for variableName, value := range variables {
pattern.Pattern = strings.ReplaceAll(pattern.Pattern, variableName, value)
}
}
return pattern
}
// retrieves a pattern from the database by name
func (o *PatternsEntity) getFromDB(name string) (ret *Pattern, err error) {
patternPath := filepath.Join(o.Dir, name, o.SystemPatternFile)
var pattern []byte
if pattern, err = os.ReadFile(patternPath); err != nil {
return
}
patternStr := string(pattern)
ret = &Pattern{
Name: name,
Pattern: patternStr,
}
return
}
func (o *PatternsEntity) PrintLatestPatterns(latestNumber int) (err error) {
var contents []byte
if contents, err = os.ReadFile(o.UniquePatternsFilePath); err != nil {
err = fmt.Errorf("could not read unique patterns file. Pleas run --updatepatterns (%s)", err)
return
}
uniquePatterns := strings.Split(string(contents), "\n")
if latestNumber > len(uniquePatterns) {
latestNumber = len(uniquePatterns)
}
for i := len(uniquePatterns) - 1; i > len(uniquePatterns)-latestNumber-1; i-- {
fmt.Println(uniquePatterns[i])
}
return
}
// reads a pattern from a file path and returns it
func (o *PatternsEntity) getFromFile(pathStr string) (*Pattern, error) {
// Handle home directory expansion
if strings.HasPrefix(pathStr, "~/") {
homedir, err := os.UserHomeDir()
if err != nil {
return nil, fmt.Errorf("could not get home directory: %v", err)
}
pathStr = filepath.Join(homedir, pathStr[2:])
}
content, err := os.ReadFile(pathStr)
if err != nil {
return nil, fmt.Errorf("could not read pattern file %s: %v", pathStr, err)
}
return &Pattern{
Name: pathStr,
Pattern: string(content),
}, nil
}
// Get required for Storage interface
func (o *PatternsEntity) Get(name string) (*Pattern, error) {
// Use GetPattern with no variables
return o.GetApplyVariables(name, nil)
}