1
0
Fork 0
mirror of https://github.com/vbatts/go-mtree.git synced 2025-10-04 12:31:00 +00:00

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>
This commit is contained in:
Aleksa Sarai 2025-09-16 18:36:14 +10:00
parent f0d9d5891f
commit ae454c4a6f
No known key found for this signature in database
GPG key ID: 2897FAD2B7E9446F

View file

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