Evaluate path predicates incrementally from cached directory paths

This commit is contained in:
Andy Dixon
2026-10-02 08:40:10 +01:00
parent 0aa93a00d9
commit 11a0e401ee
4 changed files with 33 additions and 10 deletions
+8 -1
View File
@@ -43,13 +43,20 @@ func Apply(ctx context.Context, t *inventory.Tree, q *Query, m inventory.SizeMod
r := &Result{Query: q, Mode: m, Sizes: make([]int64, n), Matched: make([]bool, n)}
covered := make([]bool, n)
c := &Ctx{Tree: t, Now: time.Now().UnixNano()}
if q.UsesPath {
c.dirPaths = map[inventory.NodeID]string{}
}
for i := range n {
if i&0xffff == 0 && ctx.Err() != nil {
return nil, ctx.Err()
}
id := inventory.NodeID(i)
nd := t.Node(id)
c.ID, c.Node = id, nd
c.ID, c.Node, c.path = id, nd, ""
if c.dirPaths != nil && nd.IsDir() {
c.path = c.lowerPath()
c.dirPaths[id] = c.path
}
if i > 0 && q.Match(c) {
r.Matched[i] = true
covered[i] = true
+21 -5
View File
@@ -16,6 +16,9 @@ type Ctx struct {
Node *inventory.Node
Now int64 // unix nanoseconds
path string
// dirPaths caches lower-cased directory paths during Apply, which visits
// parents before children, so a node's path is one concatenation.
dirPaths map[inventory.NodeID]string
}
func (c *Ctx) str(f Field) string {
@@ -25,7 +28,7 @@ func (c *Ctx) str(f Field) string {
return strings.ToLower(n.Name)
case FPath:
if c.path == "" {
c.path = strings.ToLower(c.Tree.Path(c.ID))
c.path = c.lowerPath()
}
return c.path
case FExt:
@@ -62,6 +65,22 @@ func (c *Ctx) num(f Field) int64 {
return 0
}
func (c *Ctx) lowerPath() string {
if c.dirPaths != nil {
if p, ok := c.dirPaths[c.ID]; ok {
return p
}
if pp, ok := c.dirPaths[c.Node.Parent]; ok {
sep := string(filepath.Separator)
if strings.HasSuffix(pp, sep) {
sep = ""
}
return pp + sep + strings.ToLower(c.Node.Name)
}
}
return strings.ToLower(c.Tree.Path(c.ID))
}
type node interface{ eval(*Ctx) bool }
type andNode struct{ l, r node }
@@ -154,7 +173,4 @@ func (n numNode) eval(c *Ctx) bool {
}
// Match evaluates the query against one node.
func (q *Query) Match(c *Ctx) bool {
c.path = ""
return q.root.eval(c)
}
func (q *Query) Match(c *Ctx) bool { return q.root.eval(c) }