From af75f491b889484451b6f2f5af7d91a5d4cbe356 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 26 Oct 2023 08:22:55 -0400 Subject: [PATCH] change dir resolver to include virtual path Signed-off-by: Alex Goodman --- .../cataloger/internal/all_regular_files_test.go | 2 +- syft/file/location.go | 8 ++++---- .../container_image_all_layers_test.go | 16 ++++------------ .../fileresolver/container_image_squash_test.go | 16 ++++------------ syft/internal/fileresolver/directory.go | 3 ++- syft/internal/fileresolver/directory_test.go | 5 ++++- .../internal/fileresolver/unindexed_directory.go | 3 ++- .../fileresolver/unindexed_directory_test.go | 9 ++++++--- 8 files changed, 27 insertions(+), 35 deletions(-) diff --git a/syft/file/cataloger/internal/all_regular_files_test.go b/syft/file/cataloger/internal/all_regular_files_test.go index ced33384083..07430f041da 100644 --- a/syft/file/cataloger/internal/all_regular_files_test.go +++ b/syft/file/cataloger/internal/all_regular_files_test.go @@ -48,7 +48,7 @@ func Test_allRegularFiles(t *testing.T) { return r }, wantRealPaths: strset.New("file1.txt", "nested/file2.txt"), - wantVirtualPaths: strset.New("nested/linked-file1.txt"), + wantVirtualPaths: strset.New("file1.txt", "nested/file2.txt", "nested/linked-file1.txt"), }, } for _, tt := range tests { diff --git a/syft/file/location.go b/syft/file/location.go index 65af91c5164..741f1e08322 100644 --- a/syft/file/location.go +++ b/syft/file/location.go @@ -68,6 +68,7 @@ func NewLocation(realPath string) Location { Coordinates: Coordinates{ RealPath: realPath, }, + VirtualPath: realPath, }, LocationMetadata: LocationMetadata{ Annotations: map[string]string{}, @@ -94,6 +95,7 @@ func NewLocationFromCoordinates(coordinates Coordinates) Location { return Location{ LocationData: LocationData{ Coordinates: coordinates, + VirtualPath: coordinates.RealPath, }, LocationMetadata: LocationMetadata{ Annotations: map[string]string{}, @@ -137,7 +139,8 @@ func NewLocationFromDirectory(responsePath string, ref file.Reference) Location Coordinates: Coordinates{ RealPath: responsePath, }, - ref: ref, + VirtualPath: responsePath, + ref: ref, }, LocationMetadata: LocationMetadata{ Annotations: map[string]string{}, @@ -147,9 +150,6 @@ func NewLocationFromDirectory(responsePath string, ref file.Reference) Location // NewVirtualLocationFromDirectory creates a new Location representing the given path (extracted from the Reference) relative to the given directory with a separate virtual access path. func NewVirtualLocationFromDirectory(responsePath, virtualResponsePath string, ref file.Reference) Location { - if responsePath == virtualResponsePath { - return NewLocationFromDirectory(responsePath, ref) - } return Location{ LocationData: LocationData{ Coordinates: Coordinates{ diff --git a/syft/internal/fileresolver/container_image_all_layers_test.go b/syft/internal/fileresolver/container_image_all_layers_test.go index a76082d8543..6d94d7864cc 100644 --- a/syft/internal/fileresolver/container_image_all_layers_test.go +++ b/syft/internal/fileresolver/container_image_all_layers_test.go @@ -93,9 +93,7 @@ func TestAllLayersResolver_FilesByPath(t *testing.T) { img := imagetest.GetFixtureImage(t, "docker-archive", "image-symlinks") resolver, err := NewFromContainerImageAllLayers(img) - if err != nil { - t.Fatalf("could not create resolver: %+v", err) - } + require.NoError(t, err) hasPath := resolver.HasPath(c.linkPath) if !c.forcePositiveHasPath { @@ -109,9 +107,7 @@ func TestAllLayersResolver_FilesByPath(t *testing.T) { } refs, err := resolver.FilesByPath(c.linkPath) - if err != nil { - t.Fatalf("could not use resolver: %+v", err) - } + require.NoError(t, err) if len(refs) != len(c.resolutions) { t.Fatalf("unexpected number of resolutions: %d", len(refs)) @@ -207,14 +203,10 @@ func TestAllLayersResolver_FilesByGlob(t *testing.T) { img := imagetest.GetFixtureImage(t, "docker-archive", "image-symlinks") resolver, err := NewFromContainerImageAllLayers(img) - if err != nil { - t.Fatalf("could not create resolver: %+v", err) - } + require.NoError(t, err) refs, err := resolver.FilesByGlob(c.glob) - if err != nil { - t.Fatalf("could not use resolver: %+v", err) - } + require.NoError(t, err) if len(refs) != len(c.resolutions) { t.Fatalf("unexpected number of resolutions: %d", len(refs)) diff --git a/syft/internal/fileresolver/container_image_squash_test.go b/syft/internal/fileresolver/container_image_squash_test.go index 642f6b52053..19e32d9eb52 100644 --- a/syft/internal/fileresolver/container_image_squash_test.go +++ b/syft/internal/fileresolver/container_image_squash_test.go @@ -74,9 +74,7 @@ func TestImageSquashResolver_FilesByPath(t *testing.T) { img := imagetest.GetFixtureImage(t, "docker-archive", "image-symlinks") resolver, err := NewFromContainerImageSquash(img) - if err != nil { - t.Fatalf("could not create resolver: %+v", err) - } + require.NoError(t, err) hasPath := resolver.HasPath(c.linkPath) if !c.forcePositiveHasPath { @@ -90,9 +88,7 @@ func TestImageSquashResolver_FilesByPath(t *testing.T) { } refs, err := resolver.FilesByPath(c.linkPath) - if err != nil { - t.Fatalf("could not use resolver: %+v", err) - } + require.NoError(t, err) expectedRefs := 1 if c.resolvePath == "" { @@ -187,14 +183,10 @@ func TestImageSquashResolver_FilesByGlob(t *testing.T) { img := imagetest.GetFixtureImage(t, "docker-archive", "image-symlinks") resolver, err := NewFromContainerImageSquash(img) - if err != nil { - t.Fatalf("could not create resolver: %+v", err) - } + require.NoError(t, err) refs, err := resolver.FilesByGlob(c.glob) - if err != nil { - t.Fatalf("could not use resolver: %+v", err) - } + require.NoError(t, err) expectedRefs := 1 if c.resolvePath == "" { diff --git a/syft/internal/fileresolver/directory.go b/syft/internal/fileresolver/directory.go index 766d53c8fba..0b972a2d56e 100644 --- a/syft/internal/fileresolver/directory.go +++ b/syft/internal/fileresolver/directory.go @@ -264,8 +264,9 @@ func (r *Directory) FilesByMIMEType(types ...string) ([]file.Location, error) { if uniqueFileIDs.Contains(*refVia.Reference) { continue } - location := file.NewLocationFromDirectory( + location := file.NewVirtualLocationFromDirectory( r.responsePath(string(refVia.Reference.RealPath)), + r.responsePath(string(refVia.RequestPath)), *refVia.Reference, ) uniqueFileIDs.Add(*refVia.Reference) diff --git a/syft/internal/fileresolver/directory_test.go b/syft/internal/fileresolver/directory_test.go index 09d135f9c2b..7032a43c2bd 100644 --- a/syft/internal/fileresolver/directory_test.go +++ b/syft/internal/fileresolver/directory_test.go @@ -71,7 +71,7 @@ func TestDirectoryResolver_FilesByPath_request_response(t *testing.T) { base string input string expectedRealPath string - expectedVirtualPath string + expectedVirtualPath string // note: if empty it will be assumed to match the expectedRealPath }{ { name: "relative root, relative request, direct", @@ -489,6 +489,9 @@ func TestDirectoryResolver_FilesByPath_request_response(t *testing.T) { } for _, c := range cases { t.Run(c.name, func(t *testing.T) { + if c.expectedVirtualPath == "" { + c.expectedVirtualPath = c.expectedRealPath + } // we need to mimic a shell, otherwise we won't get a path within a symlink targetPath := filepath.Join(testDir, c.cwd) diff --git a/syft/internal/fileresolver/unindexed_directory.go b/syft/internal/fileresolver/unindexed_directory.go index 68fdd7965bd..e82b3b47215 100644 --- a/syft/internal/fileresolver/unindexed_directory.go +++ b/syft/internal/fileresolver/unindexed_directory.go @@ -261,13 +261,14 @@ func (u UnindexedDirectory) Write(location file.Location, reader io.Reader) erro func (u UnindexedDirectory) newLocation(filePath string, resolveLinks bool) *file.Location { filePath = path.Clean(filePath) - virtualPath := "" + virtualPath := filePath realPath := filePath if resolveLinks { paths := u.resolveLinks(filePath) if len(paths) > 1 { realPath = paths[len(paths)-1] + // TODO: this is not quite correct, as the equivalent of os.EvalSymlinks needs to be done (in the context of afero) if realPath != path.Clean(filePath) { virtualPath = paths[0] } diff --git a/syft/internal/fileresolver/unindexed_directory_test.go b/syft/internal/fileresolver/unindexed_directory_test.go index 44ec69bf74b..0d6ecb1062a 100644 --- a/syft/internal/fileresolver/unindexed_directory_test.go +++ b/syft/internal/fileresolver/unindexed_directory_test.go @@ -96,7 +96,7 @@ func Test_UnindexDirectoryResolver_FilesByPath_request_response(t *testing.T) { base string input string expectedRealPath string - expectedVirtualPath string + expectedVirtualPath string // if empty, the virtual path should be the same as the real path }{ { name: "relative root, relative request, direct", @@ -498,6 +498,9 @@ func Test_UnindexDirectoryResolver_FilesByPath_request_response(t *testing.T) { } for _, c := range cases { t.Run(c.name, func(t *testing.T) { + if c.expectedVirtualPath == "" { + c.expectedVirtualPath = c.expectedRealPath + } // we need to mimic a shell, otherwise we won't get a path within a symlink targetPath := filepath.Join(testDir, c.cwd) @@ -1090,7 +1093,7 @@ func Test_UnindexedDirectoryResolver_resolvesLinks(t *testing.T) { file.NewLocation("file-1.txt"), file.NewLocation("file-2.txt"), file.NewLocation("file-3.txt"), - file.NewLocation("parent/file-4.txt"), + file.NewVirtualLocation("parent/file-4.txt", "parent-link/file-4.txt"), }, }, { @@ -1120,7 +1123,7 @@ func Test_UnindexedDirectoryResolver_resolvesLinks(t *testing.T) { file.NewLocation("file-1.txt"), file.NewLocation("file-2.txt"), file.NewLocation("file-3.txt"), - file.NewLocation("parent/file-4.txt"), + file.NewVirtualLocation("parent/file-4.txt", "parent-link/file-4.txt"), }, }, {