ensure resolvers ignore directories for "FilesBy*" methods

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Alex Goodman 2020-11-06 07:21:38 -05:00
parent 8095cd9980
commit 0205e72be9
No known key found for this signature in database
GPG Key ID: 5CB45AE22BAB7EA7
7 changed files with 129 additions and 8 deletions

View File

@ -67,12 +67,26 @@ func (r *AllLayersResolver) FilesByPath(paths ...file.Path) ([]file.Reference, e
for _, path := range paths {
for idx, layerIdx := range r.layers {
ref := r.img.Layers[layerIdx].Tree.File(path)
tree := r.img.Layers[layerIdx].Tree
ref := tree.File(path)
if ref == nil {
// no file found, keep looking through layers
continue
}
// don't consider directories (special case: there is no path information for /)
if ref.Path == "/" {
continue
} else if r.img.FileCatalog.Exists(*ref) {
metadata, err := r.img.FileCatalog.Get(*ref)
if err != nil {
return nil, fmt.Errorf("unable to get file metadata for path=%q: %w", ref.Path, err)
}
if metadata.Metadata.IsDir {
continue
}
}
results, err := r.fileByRef(*ref, uniqueFileIDs, idx)
if err != nil {
return nil, err
@ -97,6 +111,20 @@ func (r *AllLayersResolver) FilesByGlob(patterns ...string) ([]file.Reference, e
}
for _, ref := range refs {
// don't consider directories (special case: there is no path information for /)
if ref.Path == "/" {
continue
} else if r.img.FileCatalog.Exists(ref) {
metadata, err := r.img.FileCatalog.Get(ref)
if err != nil {
return nil, fmt.Errorf("unable to get file metadata for path=%q: %w", ref.Path, err)
}
if metadata.Metadata.IsDir {
continue
}
}
results, err := r.fileByRef(ref, uniqueFileIDs, idx)
if err != nil {
return nil, err

View File

@ -1,9 +1,10 @@
package resolvers
import (
"github.com/anchore/stereoscope/pkg/imagetest"
"testing"
"github.com/anchore/stereoscope/pkg/imagetest"
"github.com/anchore/stereoscope/pkg/file"
)
@ -80,6 +81,11 @@ func TestAllLayersResolver_FilesByPath(t *testing.T) {
},
},
},
{
name: "ignore directories",
linkPath: "/bin",
resolutions: []resolution{},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
@ -188,6 +194,11 @@ func TestAllLayersResolver_FilesByGlob(t *testing.T) {
},
},
},
{
name: "ignore directories",
glob: "**/bin",
resolutions: []resolution{},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {

View File

@ -33,12 +33,18 @@ func (s DirectoryResolver) FilesByPath(userPaths ...file.Path) ([]file.Reference
// a path relative to root should be prefixed with the resolvers directory path, otherwise it should be left as is
userStrPath = path.Join(s.Path, userStrPath)
}
_, err := os.Stat(userStrPath)
fileMeta, err := os.Stat(userStrPath)
if os.IsNotExist(err) {
continue
} else if err != nil {
log.Errorf("path (%s) is not valid: %v", userStrPath, err)
}
// don't consider directories
if fileMeta.IsDir() {
continue
}
references = append(references, file.NewFileReference(file.Path(userStrPath)))
}
@ -69,9 +75,12 @@ func (s DirectoryResolver) FilesByGlob(patterns ...string) ([]file.Reference, er
if err != nil {
continue
}
// don't consider directories
if fileMeta.IsDir() {
continue
}
matchedPath := file.Path(match)
result = append(result, file.NewFileReference(matchedPath))
}

View File

@ -48,6 +48,12 @@ func TestDirectoryResolver_FilesByPath(t *testing.T) {
expected: "test-fixtures/image-symlinks/file-1.txt",
refCount: 1,
},
{
name: "directories ignored",
root: "./test-fixtures/",
input: "/image-symlinks",
refCount: 0,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {

View File

@ -26,16 +26,32 @@ func (r *ImageSquashResolver) FilesByPath(paths ...file.Path) ([]file.Reference,
uniqueFiles := make([]file.Reference, 0)
for _, path := range paths {
ref := r.img.SquashedTree().File(path)
tree := r.img.SquashedTree()
ref := tree.File(path)
if ref == nil {
// no file found, keep looking through layers
continue
}
// don't consider directories (special case: there is no path information for /)
if ref.Path == "/" {
continue
} else if r.img.FileCatalog.Exists(*ref) {
metadata, err := r.img.FileCatalog.Get(*ref)
if err != nil {
return nil, fmt.Errorf("unable to get file metadata for path=%q: %w", ref.Path, err)
}
if metadata.Metadata.IsDir {
continue
}
}
// a file may be a symlink, process it as such and resolve it
resolvedRef, err := r.img.ResolveLinkByImageSquash(*ref)
if err != nil {
return nil, fmt.Errorf("failed to resolve link from img (ref=%+v): %w", ref, err)
}
if resolvedRef != nil && !uniqueFileIDs.Contains(*resolvedRef) {
uniqueFileIDs.Add(*resolvedRef)
uniqueFiles = append(uniqueFiles, *resolvedRef)
@ -57,6 +73,20 @@ func (r *ImageSquashResolver) FilesByGlob(patterns ...string) ([]file.Reference,
}
for _, ref := range refs {
// don't consider directories (special case: there is no path information for /)
if ref.Path == "/" {
continue
} else if r.img.FileCatalog.Exists(ref) {
metadata, err := r.img.FileCatalog.Get(ref)
if err != nil {
return nil, fmt.Errorf("unable to get file metadata for path=%q: %w", ref.Path, err)
}
if metadata.Metadata.IsDir {
continue
}
}
resolvedRefs, err := r.FilesByPath(ref.Path)
if err != nil {
return nil, fmt.Errorf("failed to find files by path (ref=%+v): %w", ref, err)

View File

@ -1,9 +1,10 @@
package resolvers
import (
"github.com/anchore/stereoscope/pkg/imagetest"
"testing"
"github.com/anchore/stereoscope/pkg/imagetest"
"github.com/anchore/stereoscope/pkg/file"
)
@ -44,6 +45,11 @@ func TestImageSquashResolver_FilesByPath(t *testing.T) {
resolveLayer: 8,
resolvePath: "/link-dead",
},
{
name: "ignore directories",
linkPath: "/bin",
resolvePath: "",
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
@ -60,10 +66,20 @@ func TestImageSquashResolver_FilesByPath(t *testing.T) {
t.Fatalf("could not use resolver: %+v", err)
}
if len(refs) != 1 {
expectedRefs := 1
if c.resolvePath == "" {
expectedRefs = 0
}
if len(refs) != expectedRefs {
t.Fatalf("unexpected number of resolutions: %d", len(refs))
}
if expectedRefs == 0 {
// nothing else to assert
return
}
actual := refs[0]
if actual.Path != file.Path(c.resolvePath) {
@ -119,6 +135,11 @@ func TestImageSquashResolver_FilesByGlob(t *testing.T) {
resolveLayer: 8,
resolvePath: "/link-dead",
},
{
name: "ignore directories",
glob: "**/bin",
resolvePath: "",
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
@ -135,10 +156,20 @@ func TestImageSquashResolver_FilesByGlob(t *testing.T) {
t.Fatalf("could not use resolver: %+v", err)
}
if len(refs) != 1 {
expectedRefs := 1
if c.resolvePath == "" {
expectedRefs = 0
}
if len(refs) != expectedRefs {
t.Fatalf("unexpected number of resolutions: %d", len(refs))
}
if expectedRefs == 0 {
// nothing else to assert
return
}
actual := refs[0]
if actual.Path != file.Path(c.resolvePath) {

View File

@ -61,9 +61,15 @@ func TestDirectoryScope(t *testing.T) {
{
desc: "path detected",
input: "test-fixtures",
inputPaths: []file.Path{file.Path("test-fixtures/path-detected")},
inputPaths: []file.Path{file.Path("test-fixtures/path-detected/.vimrc")},
expRefs: 1,
},
{
desc: "directory ignored",
input: "test-fixtures",
inputPaths: []file.Path{file.Path("test-fixtures/path-detected")},
expRefs: 0,
},
{
desc: "no files-by-path detected",
input: "test-fixtures",