From d79f714aaeb79160f9553858b82813ad815756ac Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Dec 2025 04:16:55 +0000 Subject: [PATCH] perf(expression): use streaming hash in hashFiles() to reduce memory usage Changed from loading all file contents into memory to streaming each file directly into the hash. This prevents memory issues when matching many large files with patterns like 'hashFiles("**/*.go")'. --- internal/expression/evaluator.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/internal/expression/evaluator.go b/internal/expression/evaluator.go index a1d0c3c..6b8bcfe 100644 --- a/internal/expression/evaluator.go +++ b/internal/expression/evaluator.go @@ -4,6 +4,7 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + "io" "os" "path/filepath" "sort" @@ -373,6 +374,7 @@ func evalEndsWith(args []Node, ctx *EvaluationContext) (bool, error) { // evalHashFiles evaluates the hashFiles(pattern...) function. // Returns the SHA256 hash of the contents of files matching the patterns. +// Uses streaming hash to avoid loading all file contents into memory. func evalHashFiles(args []Node, ctx *EvaluationContext) (string, error) { if len(args) == 0 { return "", nil @@ -387,7 +389,9 @@ func evalHashFiles(args []Node, ctx *EvaluationContext) (string, error) { } } - var allBytes []byte + h := sha256.New() + hasContent := false + for _, arg := range args { patternVal, err := evaluateNode(arg, ctx) if err != nil { @@ -409,20 +413,26 @@ func evalHashFiles(args []Node, ctx *EvaluationContext) (string, error) { if err != nil || info.IsDir() { continue } - data, err := os.ReadFile(match) + + f, err := os.Open(match) + if err != nil { + continue + } + + _, err = io.Copy(h, f) + f.Close() if err != nil { continue } - allBytes = append(allBytes, data...) + hasContent = true } } - if len(allBytes) == 0 { + if !hasContent { return "", nil } - hash := sha256.Sum256(allBytes) - return hex.EncodeToString(hash[:]), nil + return hex.EncodeToString(h.Sum(nil)), nil } // toBool converts a value to a boolean.