File 0023-cmd-validate-restructure-filtering-to-use-filter-fun.patch of Package go-mtree

From ae454c4a6f84f3e2dffe0d1b01f3ea4a1497a2dd Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <cyphar@cyphar.com>
Date: Tue, 16 Sep 2025 18:36:14 +1000
Subject: [PATCH 23/25] cmd: validate: restructure filtering to use filter
 functions

This lets us modernise the filtering logic a little bit, and also allows
us to configure which filters we wish to apply (a future patch will
move some of the filtering done in the top-level go-mtree package to the
cmd/validate package).

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
---
 cmd/gomtree/cmd/validate.go | 91 ++++++++++++++++++++-----------------
 1 file changed, 49 insertions(+), 42 deletions(-)

diff --git a/cmd/gomtree/cmd/validate.go b/cmd/gomtree/cmd/validate.go
index f3b5fa613c73..7186be3fbe3f 100644
--- a/cmd/gomtree/cmd/validate.go
+++ b/cmd/gomtree/cmd/validate.go
@@ -362,11 +362,15 @@ func validateAction(c *cli.Context) error {
 		if err != nil {
 			return err
 		}
-		if res != nil {
-			if isTarSpec(specDh) || c.String("tar") != "" {
-				res = filterMissingKeywords(res)
-			}
 
+		// Apply filters.
+		var filters []deltaFilterFn
+		if isTarSpec(specDh) || c.String("tar") != "" {
+			filters = append(filters, tarKeywordFilter)
+		}
+		res = filterDeltas(res, filters...)
+
+		if len(res) > 0 {
 			out := formatFunc(res)
 			if _, err := os.Stdout.Write([]byte(out)); err != nil {
 				return err
@@ -430,48 +434,51 @@ func isDirEntry(e mtree.Entry) bool {
 	return false
 }
 
-// filterMissingKeywords is a fairly annoying hack to get around the fact that
-// tar archive manifest generation has certain unsolveable problems regarding
-// certain keywords. For example, the size=... keyword cannot be implemented
-// for directories in a tar archive (which causes Missing errors for that
-// keyword).
-//
-// This function just removes all instances of Missing errors for keywords.
-// This makes certain assumptions about the type of issues tar archives have.
-// Only call this on tar archive manifest comparisons.
-func filterMissingKeywords(diffs []mtree.InodeDelta) []mtree.InodeDelta {
-	newDiffs := []mtree.InodeDelta{}
-loop:
-	for _, diff := range diffs {
-		if diff.Type() == mtree.Modified {
-			// We only apply this filtering to directories.
-			// NOTE: This will probably break if someone drops the size keyword.
-			if isDirEntry(*diff.Old()) || isDirEntry(*diff.New()) {
-				// If this applies to '.' then we just filter everything
-				// (meaning we remove this entry). This is because note all tar
-				// archives include a '.' entry. Which makes checking this not
-				// practical.
-				if diff.Path() == "." {
-					continue
-				}
+// tarKeywordFilter is a filter for diffs produced where one half is a tar
+// archive. tar archive manifests do not have a "size" key associated with
+// directories (due to limitations in manifest generation for tar archives) and
+// so any deltas due to size missing should be removed.
+func tarKeywordFilter(delta *mtree.InodeDelta) bool {
+	if delta.Path() == "." {
+		// Not all tar archives include a root entry so we should skip that
+		// entry if we run into a diff that claims there is an issue with
+		// it.
+		return false
+	}
+	if delta.Type() != mtree.Modified {
+		return true
+	}
+	// Strip out "size" entries for directory entries.
+	if isDirEntry(*delta.Old()) || isDirEntry(*delta.New()) {
+		keys := delta.DiffPtr()
+		*keys = slices.DeleteFunc(*keys, func(kd mtree.KeyDelta) bool {
+			return kd.Name() == "size"
+		})
+	}
+	return true
+}
 
-				// Only filter out the size keyword.
-				keys := diff.DiffPtr()
-				*keys = slices.DeleteFunc(*keys, func(kd mtree.KeyDelta) bool {
-					return kd.Name() == "size"
-				})
-				// If there are no key deltas left after filtering, the entry
-				// should be filtered out entirely.
-				if len(*keys) == 0 {
-					continue loop
-				}
+type deltaFilterFn func(*mtree.InodeDelta) bool
+
+// filterDeltas takes the set of deltas generated by mtree and applies the
+// given set of filters to it.
+func filterDeltas(deltas []mtree.InodeDelta, filters ...deltaFilterFn) []mtree.InodeDelta {
+	filtered := make([]mtree.InodeDelta, 0, len(deltas))
+next:
+	for _, delta := range deltas {
+		for _, filter := range filters {
+			if !filter(&delta) {
+				continue next
 			}
 		}
-
-		// If we got here, append to the new set.
-		newDiffs = append(newDiffs, diff)
+		// Some filters might modify the entry to remove keyword deltas --
+		// if there are no deltas left then we should skip the entry entirely.
+		if delta.Type() == mtree.Modified && len(delta.Diff()) == 0 {
+			continue next
+		}
+		filtered = append(filtered, delta)
 	}
-	return newDiffs
+	return filtered
 }
 
 // isTarSpec returns whether the spec provided came from the tar generator.
-- 
2.51.0

openSUSE Build Service is sponsored by