diff --git a/syft/file/cataloger/internal/all_regular_files_test.go b/syft/file/cataloger/internal/all_regular_files_test.go index ced333840..07430f041 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 65af91c51..741f1e083 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 a76082d85..6d94d7864 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 642f6b520..19e32d9eb 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 766d53c8f..0b972a2d5 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 09d135f9c..7032a43c2 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 68fdd7965..e82b3b472 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 44ec69bf7..0d6ecb106 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"), }, }, {