diff --git a/content/adaptor.go b/content/adaptor.go new file mode 100644 index 000000000..171d7fad8 --- /dev/null +++ b/content/adaptor.go @@ -0,0 +1,52 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package content + +import ( + "strings" + + "github.com/containerd/containerd/filters" +) + +// AdoptInfo returns `filters.Adaptor` that handles `content.Info`. +func AdaptInfo(info Info) filters.Adaptor { + return filters.AdapterFunc(func(fieldpath []string) (string, bool) { + if len(fieldpath) == 0 { + return "", false + } + + switch fieldpath[0] { + case "digest": + return info.Digest.String(), true + case "size": + // TODO: support size based filtering + case "labels": + return checkMap(fieldpath[1:], info.Labels) + } + + return "", false + }) +} + +func checkMap(fieldpath []string, m map[string]string) (string, bool) { + if len(m) == 0 { + return "", false + } + + value, ok := m[strings.Join(fieldpath, ".")] + return value, ok +} diff --git a/content/local/store.go b/content/local/store.go index 87056814a..af5dc330c 100644 --- a/content/local/store.go +++ b/content/local/store.go @@ -240,9 +240,14 @@ func (s *store) Update(ctx context.Context, info content.Info, fieldpaths ...str return info, nil } -func (s *store) Walk(ctx context.Context, fn content.WalkFunc, filters ...string) error { - // TODO: Support filters +func (s *store) Walk(ctx context.Context, fn content.WalkFunc, fs ...string) error { root := filepath.Join(s.root, "blobs") + + filter, err := filters.ParseAll(fs...) + if err != nil { + return err + } + var alg digest.Algorithm return filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { if err != nil { @@ -286,7 +291,12 @@ func (s *store) Walk(ctx context.Context, fn content.WalkFunc, filters ...string return err } } - return fn(s.info(dgst, fi, labels)) + + info := s.info(dgst, fi, labels) + if !filter.Match(content.AdaptInfo(info)) { + return nil + } + return fn(info) }) } diff --git a/metadata/adaptors.go b/metadata/adaptors.go index b165c38e0..c5d576f84 100644 --- a/metadata/adaptors.go +++ b/metadata/adaptors.go @@ -90,25 +90,6 @@ func adaptContainer(o interface{}) filters.Adaptor { }) } -func adaptContentInfo(info content.Info) filters.Adaptor { - return filters.AdapterFunc(func(fieldpath []string) (string, bool) { - if len(fieldpath) == 0 { - return "", false - } - - switch fieldpath[0] { - case "digest": - return info.Digest.String(), true - case "size": - // TODO: support size based filtering - case "labels": - return checkMap(fieldpath[1:], info.Labels) - } - - return "", false - }) -} - func adaptContentStatus(status content.Status) filters.Adaptor { return filters.AdapterFunc(func(fieldpath []string) (string, bool) { if len(fieldpath) == 0 { diff --git a/metadata/content.go b/metadata/content.go index 268a9b1b7..190b7bed7 100644 --- a/metadata/content.go +++ b/metadata/content.go @@ -181,7 +181,7 @@ func (cs *contentStore) Walk(ctx context.Context, fn content.WalkFunc, fs ...str if err := readInfo(&info, bkt.Bucket(k)); err != nil { return err } - if filter.Match(adaptContentInfo(info)) { + if filter.Match(content.AdaptInfo(info)) { infos = append(infos, info) } return nil