mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
Fix directory resolver to consider CWD and root path input correctly (#1840)
* [wip] put in initial fix Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * capture expected behavior of dir resolver in tests Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * update tests + comments to reflect current dir resolver behavior Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add additional test cases Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * fix linting Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * fix additional tests Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * fix bad merge conflict resolution Signed-off-by: Alex Goodman <alex.goodman@anchore.com> --------- Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
07e76907f6
commit
6afbffce28
@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/anchore/syft/syft/sbom"
|
"github.com/anchore/syft/syft/sbom"
|
||||||
"github.com/anchore/syft/syft/source"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Add ToFormatModel tests
|
// TODO: Add ToFormatModel tests
|
||||||
@ -505,14 +504,14 @@ func Test_toSPDXID(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "short filename",
|
name: "short filename",
|
||||||
it: source.Coordinates{
|
it: file.Coordinates{
|
||||||
RealPath: "/short/path/file.txt",
|
RealPath: "/short/path/file.txt",
|
||||||
},
|
},
|
||||||
expected: "File-short-path-file.txt",
|
expected: "File-short-path-file.txt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "long filename",
|
name: "long filename",
|
||||||
it: source.Coordinates{
|
it: file.Coordinates{
|
||||||
RealPath: "/some/long/path/with/a/lot/of-text/that-contains-a/file.txt",
|
RealPath: "/some/long/path/with/a/lot/of-text/that-contains-a/file.txt",
|
||||||
},
|
},
|
||||||
expected: "File-...a-lot-of-text-that-contains-a-file.txt",
|
expected: "File-...a-lot-of-text-that-contains-a-file.txt",
|
||||||
|
|||||||
@ -54,12 +54,6 @@ func newFromDirectoryWithoutIndex(root string, base string, pathFilters ...PathI
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not get CWD: %w", err)
|
return nil, fmt.Errorf("could not get CWD: %w", err)
|
||||||
}
|
}
|
||||||
// we have to account for the root being accessed through a symlink path and always resolve the real path. Otherwise
|
|
||||||
// we will not be able to normalize given paths that fall under the resolver
|
|
||||||
cleanCWD, err := filepath.EvalSymlinks(currentWD)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not evaluate CWD symlinks: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanRoot, err := filepath.EvalSymlinks(root)
|
cleanRoot, err := filepath.EvalSymlinks(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -80,7 +74,7 @@ func newFromDirectoryWithoutIndex(root string, base string, pathFilters ...PathI
|
|||||||
|
|
||||||
var currentWdRelRoot string
|
var currentWdRelRoot string
|
||||||
if path.IsAbs(cleanRoot) {
|
if path.IsAbs(cleanRoot) {
|
||||||
currentWdRelRoot, err = filepath.Rel(cleanCWD, cleanRoot)
|
currentWdRelRoot, err = filepath.Rel(currentWD, cleanRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not determine given root path to CWD: %w", err)
|
return nil, fmt.Errorf("could not determine given root path to CWD: %w", err)
|
||||||
}
|
}
|
||||||
@ -91,7 +85,7 @@ func newFromDirectoryWithoutIndex(root string, base string, pathFilters ...PathI
|
|||||||
return &Directory{
|
return &Directory{
|
||||||
path: cleanRoot,
|
path: cleanRoot,
|
||||||
base: cleanBase,
|
base: cleanBase,
|
||||||
currentWd: cleanCWD,
|
currentWd: currentWD,
|
||||||
currentWdRelativeToRoot: currentWdRelRoot,
|
currentWdRelativeToRoot: currentWdRelRoot,
|
||||||
tree: filetree.New(),
|
tree: filetree.New(),
|
||||||
index: filetree.NewIndex(),
|
index: filetree.NewIndex(),
|
||||||
@ -132,6 +126,7 @@ func (r Directory) requestPath(userPath string) (string, error) {
|
|||||||
return userPath, nil
|
return userPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// responsePath takes a path from the underlying fs domain and converts it to a path that is relative to the root of the directory resolver.
|
||||||
func (r Directory) responsePath(path string) string {
|
func (r Directory) responsePath(path string) string {
|
||||||
// check to see if we need to encode back to Windows from posix
|
// check to see if we need to encode back to Windows from posix
|
||||||
if runtime.GOOS == WindowsOS {
|
if runtime.GOOS == WindowsOS {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/wagoodman/go-partybus"
|
"github.com/wagoodman/go-partybus"
|
||||||
"github.com/wagoodman/go-progress"
|
"github.com/wagoodman/go-progress"
|
||||||
@ -119,6 +120,22 @@ func (r *directoryIndexer) indexTree(root string, stager *progress.Stage) ([]str
|
|||||||
return roots, nil
|
return roots, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shouldIndexFullTree, err := isRealPath(root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !shouldIndexFullTree {
|
||||||
|
newRoots, err := r.indexBranch(root, stager)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to index branch=%q: %w", root, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
roots = append(roots, newRoots...)
|
||||||
|
|
||||||
|
return roots, nil
|
||||||
|
}
|
||||||
|
|
||||||
err = filepath.Walk(root,
|
err = filepath.Walk(root,
|
||||||
func(path string, info os.FileInfo, err error) error {
|
func(path string, info os.FileInfo, err error) error {
|
||||||
stager.Current = path
|
stager.Current = path
|
||||||
@ -143,6 +160,85 @@ func (r *directoryIndexer) indexTree(root string, stager *progress.Stage) ([]str
|
|||||||
return roots, nil
|
return roots, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRealPath(root string) (bool, error) {
|
||||||
|
rootParent := filepath.Clean(filepath.Dir(root))
|
||||||
|
|
||||||
|
realRootParent, err := filepath.EvalSymlinks(rootParent)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
realRootParent = filepath.Clean(realRootParent)
|
||||||
|
|
||||||
|
return rootParent == realRootParent, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *directoryIndexer) indexBranch(root string, stager *progress.Stage) ([]string, error) {
|
||||||
|
rootRealPath, err := filepath.EvalSymlinks(root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// there is a symlink within the path to the root, we need to index the real root parent first
|
||||||
|
// then capture the symlinks to the root path
|
||||||
|
roots, err := r.indexTree(rootRealPath, stager)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to index real root=%q: %w", rootRealPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// walk down all ancestor paths and shallow-add non-existing elements to the tree
|
||||||
|
for idx, p := range allContainedPaths(root) {
|
||||||
|
var targetPath string
|
||||||
|
if idx != 0 {
|
||||||
|
parent := path.Dir(p)
|
||||||
|
cleanParent, err := filepath.EvalSymlinks(parent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to evaluate symlink for contained path parent=%q: %w", parent, err)
|
||||||
|
}
|
||||||
|
targetPath = filepath.Join(cleanParent, filepath.Base(p))
|
||||||
|
} else {
|
||||||
|
targetPath = p
|
||||||
|
}
|
||||||
|
|
||||||
|
stager.Current = targetPath
|
||||||
|
|
||||||
|
lstat, err := os.Lstat(targetPath)
|
||||||
|
newRoot, err := r.indexPath(targetPath, lstat, err)
|
||||||
|
if err != nil && !errors.Is(err, ErrSkipPath) && !errors.Is(err, fs.SkipDir) {
|
||||||
|
return nil, fmt.Errorf("unable to index ancestor path=%q: %w", targetPath, err)
|
||||||
|
}
|
||||||
|
if newRoot != "" {
|
||||||
|
roots = append(roots, newRoot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return roots, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func allContainedPaths(p string) []string {
|
||||||
|
var all []string
|
||||||
|
var currentPath string
|
||||||
|
|
||||||
|
cleanPath := strings.TrimSpace(p)
|
||||||
|
|
||||||
|
if cleanPath == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate through all parts of the path, replacing path elements with link resolutions where possible.
|
||||||
|
for idx, part := range strings.Split(filepath.Clean(cleanPath), file.DirSeparator) {
|
||||||
|
if idx == 0 && part == "" {
|
||||||
|
currentPath = file.DirSeparator
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// cumulatively gather where we are currently at and provide a rich object
|
||||||
|
currentPath = path.Join(currentPath, part)
|
||||||
|
all = append(all, currentPath)
|
||||||
|
}
|
||||||
|
return all
|
||||||
|
}
|
||||||
|
|
||||||
func (r *directoryIndexer) indexPath(path string, info os.FileInfo, err error) (string, error) {
|
func (r *directoryIndexer) indexPath(path string, info os.FileInfo, err error) (string, error) {
|
||||||
// ignore any path which a filter function returns true
|
// ignore any path which a filter function returns true
|
||||||
for _, filterFn := range r.pathIndexVisitors {
|
for _, filterFn := range r.pathIndexVisitors {
|
||||||
|
|||||||
@ -226,8 +226,8 @@ func TestDirectoryIndexer_SkipsAlreadyVisitedLinkDestinations(t *testing.T) {
|
|||||||
var observedPaths []string
|
var observedPaths []string
|
||||||
pathObserver := func(p string, _ os.FileInfo, _ error) error {
|
pathObserver := func(p string, _ os.FileInfo, _ error) error {
|
||||||
fields := strings.Split(p, "test-fixtures/symlinks-prune-indexing")
|
fields := strings.Split(p, "test-fixtures/symlinks-prune-indexing")
|
||||||
if len(fields) != 2 {
|
if len(fields) < 2 {
|
||||||
t.Fatalf("unable to parse path: %s", p)
|
return nil
|
||||||
}
|
}
|
||||||
clean := strings.TrimLeft(fields[1], "/")
|
clean := strings.TrimLeft(fields[1], "/")
|
||||||
if clean != "" {
|
if clean != "" {
|
||||||
@ -261,9 +261,11 @@ func TestDirectoryIndexer_SkipsAlreadyVisitedLinkDestinations(t *testing.T) {
|
|||||||
"path/5/6/7/8/dont-index-me-twice-either.txt",
|
"path/5/6/7/8/dont-index-me-twice-either.txt",
|
||||||
"path/file.txt",
|
"path/file.txt",
|
||||||
// everything below is after the original tree is indexed, and we are now indexing additional roots from symlinks
|
// everything below is after the original tree is indexed, and we are now indexing additional roots from symlinks
|
||||||
"path", // considered from symlink before-path, but pruned
|
"path", // considered from symlink before-path, but pruned
|
||||||
"before-path/file.txt", // considered from symlink c-file.txt, but pruned
|
"path/file.txt", // leaf
|
||||||
"before-path", // considered from symlink c-path, but pruned
|
"before-path", // considered from symlink c-path, but pruned
|
||||||
|
"path/file.txt", // leaf
|
||||||
|
"before-path", // considered from symlink c-path, but pruned
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, expected, observedPaths, "visited paths differ \n %s", cmp.Diff(expected, observedPaths))
|
assert.Equal(t, expected, observedPaths, "visited paths differ \n %s", cmp.Diff(expected, observedPaths))
|
||||||
@ -282,7 +284,7 @@ func TestDirectoryIndexer_IndexesAllTypes(t *testing.T) {
|
|||||||
for _, ref := range allRefs {
|
for _, ref := range allRefs {
|
||||||
fields := strings.Split(string(ref.RealPath), "test-fixtures/symlinks-prune-indexing")
|
fields := strings.Split(string(ref.RealPath), "test-fixtures/symlinks-prune-indexing")
|
||||||
if len(fields) != 2 {
|
if len(fields) != 2 {
|
||||||
t.Fatalf("unable to parse path: %s", ref.RealPath)
|
continue
|
||||||
}
|
}
|
||||||
clean := strings.TrimLeft(fields[1], "/")
|
clean := strings.TrimLeft(fields[1], "/")
|
||||||
if clean == "" {
|
if clean == "" {
|
||||||
@ -326,3 +328,58 @@ func TestDirectoryIndexer_IndexesAllTypes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_allContainedPaths(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
path string
|
||||||
|
want []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
path: "",
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single relative",
|
||||||
|
path: "a",
|
||||||
|
want: []string{"a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single absolute",
|
||||||
|
path: "/a",
|
||||||
|
want: []string{"/a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple relative",
|
||||||
|
path: "a/b/c",
|
||||||
|
want: []string{"a", "a/b", "a/b/c"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple absolute",
|
||||||
|
path: "/a/b/c",
|
||||||
|
want: []string{"/a", "/a/b", "/a/b/c"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple absolute with extra slashs",
|
||||||
|
path: "///a/b//c/",
|
||||||
|
want: []string{"/a", "/a/b", "/a/b/c"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative with single dot",
|
||||||
|
path: "a/./b",
|
||||||
|
want: []string{"a", "a/b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative with double single dot",
|
||||||
|
path: "a/../b",
|
||||||
|
want: []string{"b"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
assert.Equal(t, tt.want, allContainedPaths(tt.path))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -22,6 +22,501 @@ import (
|
|||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestDirectoryResolver_FilesByPath_request_response(t *testing.T) {
|
||||||
|
// /
|
||||||
|
// somewhere/
|
||||||
|
// outside.txt
|
||||||
|
// root-link -> ./
|
||||||
|
// path/
|
||||||
|
// to/
|
||||||
|
// abs-inside.txt -> /path/to/the/file.txt # absolute link to somewhere inside of the root
|
||||||
|
// rel-inside.txt -> ./the/file.txt # relative link to somewhere inside of the root
|
||||||
|
// the/
|
||||||
|
// file.txt
|
||||||
|
// abs-outside.txt -> /somewhere/outside.txt # absolute link to outside of the root
|
||||||
|
// rel-outside -> ../../../somewhere/outside.txt # relative link to outside of the root
|
||||||
|
//
|
||||||
|
|
||||||
|
testDir, err := os.Getwd()
|
||||||
|
require.NoError(t, err)
|
||||||
|
relative := filepath.Join("test-fixtures", "req-resp")
|
||||||
|
absolute := filepath.Join(testDir, relative)
|
||||||
|
|
||||||
|
absInsidePath := filepath.Join(absolute, "path", "to", "abs-inside.txt")
|
||||||
|
absOutsidePath := filepath.Join(absolute, "path", "to", "the", "abs-outside.txt")
|
||||||
|
|
||||||
|
relativeViaLink := filepath.Join(relative, "root-link")
|
||||||
|
absoluteViaLink := filepath.Join(absolute, "root-link")
|
||||||
|
|
||||||
|
relativeViaDoubleLink := filepath.Join(relative, "root-link", "root-link")
|
||||||
|
absoluteViaDoubleLink := filepath.Join(absolute, "root-link", "root-link")
|
||||||
|
|
||||||
|
cleanup := func() {
|
||||||
|
_ = os.Remove(absInsidePath)
|
||||||
|
_ = os.Remove(absOutsidePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the absolute symlinks are cleaned up from any previous runs
|
||||||
|
cleanup()
|
||||||
|
|
||||||
|
require.NoError(t, os.Symlink(filepath.Join(absolute, "path", "to", "the", "file.txt"), absInsidePath))
|
||||||
|
require.NoError(t, os.Symlink(filepath.Join(absolute, "somewhere", "outside.txt"), absOutsidePath))
|
||||||
|
|
||||||
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
cwd string
|
||||||
|
root string
|
||||||
|
base string
|
||||||
|
input string
|
||||||
|
expectedRealPath string
|
||||||
|
expectedVirtualPath string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, direct",
|
||||||
|
root: relative,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, direct",
|
||||||
|
root: absolute,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, direct",
|
||||||
|
root: relative,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, direct",
|
||||||
|
root: absolute,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within root...
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, direct, cwd within root",
|
||||||
|
cwd: filepath.Join(relative, "path/to"),
|
||||||
|
root: "../../",
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, direct, cwd within root",
|
||||||
|
cwd: filepath.Join(relative, "path/to"),
|
||||||
|
root: absolute,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, direct, cwd within root",
|
||||||
|
cwd: filepath.Join(relative, "path/to"),
|
||||||
|
root: "../../",
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, direct, cwd within root",
|
||||||
|
cwd: filepath.Join(relative, "path/to"),
|
||||||
|
|
||||||
|
root: absolute,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within symlink root...
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "./",
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
// note: why not expect "path/to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "path/to/the/file.txt",
|
||||||
|
expectedVirtualPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: absoluteViaLink,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "./",
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
// note: why not expect "path/to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "path/to/the/file.txt",
|
||||||
|
expectedVirtualPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: absoluteViaLink,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within symlink root, request nested within...
|
||||||
|
{
|
||||||
|
name: "relative root, relative nested request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "./path",
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
// note: why not expect "to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "to/the/file.txt",
|
||||||
|
expectedVirtualPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative nested request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absoluteViaLink, "path"),
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs nested request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "./path",
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
// note: why not expect "to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "to/the/file.txt",
|
||||||
|
expectedVirtualPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs nested request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absoluteViaLink, "path"),
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within DOUBLE symlink root...
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "./",
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
// note: why not expect "path/to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "path/to/the/file.txt",
|
||||||
|
expectedVirtualPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: absoluteViaDoubleLink,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "./",
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
// note: why not expect "path/to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "path/to/the/file.txt",
|
||||||
|
expectedVirtualPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: absoluteViaDoubleLink,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within DOUBLE symlink root, request nested within...
|
||||||
|
{
|
||||||
|
name: "relative root, relative nested request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "./path",
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
// note: why not expect "path/to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "to/the/file.txt",
|
||||||
|
expectedVirtualPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative nested request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: filepath.Join(absoluteViaDoubleLink, "path"),
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs nested request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "./path",
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
// note: why not expect "path/to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "to/the/file.txt",
|
||||||
|
expectedVirtualPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs nested request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: filepath.Join(absoluteViaDoubleLink, "path"),
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within DOUBLE symlink root, request nested DEEP within...
|
||||||
|
{
|
||||||
|
name: "relative root, relative nested request, direct, cwd deep within (double) symlink root",
|
||||||
|
cwd: filepath.Join(relativeViaDoubleLink, "path", "to"),
|
||||||
|
root: "../",
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
// note: why not expect "path/to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "to/the/file.txt",
|
||||||
|
expectedVirtualPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative nested request, direct, cwd deep within (double) symlink root",
|
||||||
|
cwd: filepath.Join(relativeViaDoubleLink, "path", "to"),
|
||||||
|
root: filepath.Join(absoluteViaDoubleLink, "path"),
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs nested request, direct, cwd deep within (double) symlink root",
|
||||||
|
cwd: filepath.Join(relativeViaDoubleLink, "path", "to"),
|
||||||
|
root: "../",
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
// note: why not expect "path/to/the/file.txt" here?
|
||||||
|
// this is because we don't know that the path used to access this path (which is a link within
|
||||||
|
// the root) resides within the root. Without this information it appears as if this file resides
|
||||||
|
// outside the root.
|
||||||
|
expectedRealPath: filepath.Join(absolute, "path/to/the/file.txt"),
|
||||||
|
//expectedRealPath: "to/the/file.txt",
|
||||||
|
expectedVirtualPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs nested request, direct, cwd deep within (double) symlink root",
|
||||||
|
cwd: filepath.Join(relativeViaDoubleLink, "path", "to"),
|
||||||
|
root: filepath.Join(absoluteViaDoubleLink, "path"),
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
// link to outside of root cases...
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, abs indirect (outside of root)",
|
||||||
|
root: filepath.Join(relative, "path"),
|
||||||
|
input: "to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, abs indirect (outside of root)",
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, abs indirect (outside of root)",
|
||||||
|
root: filepath.Join(relative, "path"),
|
||||||
|
input: "/to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, abs indirect (outside of root)",
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, relative indirect (outside of root)",
|
||||||
|
root: filepath.Join(relative, "path"),
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, relative indirect (outside of root)",
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, relative indirect (outside of root)",
|
||||||
|
root: filepath.Join(relative, "path"),
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, relative indirect (outside of root)",
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
// link to outside of root cases... cwd within symlink root
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, abs indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "path",
|
||||||
|
input: "to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, abs indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, abs indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "path",
|
||||||
|
input: "/to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, abs indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, relative indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "path",
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, relative indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, relative indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "path",
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, relative indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, relative indirect (outside of root), cwd within DOUBLE symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "path",
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, relative indirect (outside of root), cwd within DOUBLE symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, relative indirect (outside of root), cwd within DOUBLE symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "path",
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, relative indirect (outside of root), cwd within DOUBLE symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
|
||||||
|
// we need to mimic a shell, otherwise we won't get a path within a symlink
|
||||||
|
targetPath := filepath.Join(testDir, c.cwd)
|
||||||
|
t.Setenv("PWD", filepath.Clean(targetPath))
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, os.Chdir(targetPath))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
require.NoError(t, os.Chdir(testDir))
|
||||||
|
})
|
||||||
|
|
||||||
|
resolver, err := NewFromDirectory(c.root, c.base)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, resolver)
|
||||||
|
|
||||||
|
refs, err := resolver.FilesByPath(c.input)
|
||||||
|
require.NoError(t, err)
|
||||||
|
if c.expectedRealPath == "" {
|
||||||
|
require.Empty(t, refs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.Len(t, refs, 1)
|
||||||
|
assert.Equal(t, c.expectedRealPath, refs[0].RealPath, "real path different")
|
||||||
|
assert.Equal(t, c.expectedVirtualPath, refs[0].VirtualPath, "virtual path different")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDirectoryResolver_FilesByPath_relativeRoot(t *testing.T) {
|
func TestDirectoryResolver_FilesByPath_relativeRoot(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
./the/file.txt
|
||||||
@ -0,0 +1 @@
|
|||||||
|
file-1
|
||||||
@ -0,0 +1 @@
|
|||||||
|
../../../somewhere/outside.txt
|
||||||
1
syft/internal/fileresolver/test-fixtures/req-resp/root-link
Symbolic link
1
syft/internal/fileresolver/test-fixtures/req-resp/root-link
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
./
|
||||||
@ -0,0 +1 @@
|
|||||||
|
file-2
|
||||||
@ -23,6 +23,509 @@ import (
|
|||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Test_UnindexDirectoryResolver_RequestRelativePathWithinSymlink(t *testing.T) {
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
|
||||||
|
// we need to mimic a shell, otherwise we won't get a path within a symlink
|
||||||
|
targetPath := filepath.Join(pwd, "./test-fixtures/symlinked-root/nested/link-root/nested")
|
||||||
|
t.Setenv("PWD", targetPath)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, os.Chdir(targetPath))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
require.NoError(t, os.Chdir(pwd))
|
||||||
|
})
|
||||||
|
|
||||||
|
resolver := NewFromUnindexedDirectory("./")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
locations, err := resolver.FilesByPath("file2.txt")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, locations, 1)
|
||||||
|
|
||||||
|
// TODO: this is technically not correct behavior since this is reporting the symlink path (virtual path) and
|
||||||
|
// not the real path.
|
||||||
|
require.False(t, filepath.IsAbs(locations[0].RealPath), "should be relative path")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_UnindexDirectoryResolver_FilesByPath_request_response(t *testing.T) {
|
||||||
|
// /
|
||||||
|
// somewhere/
|
||||||
|
// outside.txt
|
||||||
|
// root-link -> ./
|
||||||
|
// path/
|
||||||
|
// to/
|
||||||
|
// abs-inside.txt -> /path/to/the/file.txt # absolute link to somewhere inside of the root
|
||||||
|
// rel-inside.txt -> ./the/file.txt # relative link to somewhere inside of the root
|
||||||
|
// the/
|
||||||
|
// file.txt
|
||||||
|
// abs-outside.txt -> /somewhere/outside.txt # absolute link to outside of the root
|
||||||
|
// rel-outside -> ../../../somewhere/outside.txt # relative link to outside of the root
|
||||||
|
//
|
||||||
|
|
||||||
|
testDir, err := os.Getwd()
|
||||||
|
require.NoError(t, err)
|
||||||
|
relative := filepath.Join("test-fixtures", "req-resp")
|
||||||
|
absolute := filepath.Join(testDir, relative)
|
||||||
|
|
||||||
|
absInsidePath := filepath.Join(absolute, "path", "to", "abs-inside.txt")
|
||||||
|
absOutsidePath := filepath.Join(absolute, "path", "to", "the", "abs-outside.txt")
|
||||||
|
|
||||||
|
relativeViaLink := filepath.Join(relative, "root-link")
|
||||||
|
absoluteViaLink := filepath.Join(absolute, "root-link")
|
||||||
|
|
||||||
|
relativeViaDoubleLink := filepath.Join(relative, "root-link", "root-link")
|
||||||
|
absoluteViaDoubleLink := filepath.Join(absolute, "root-link", "root-link")
|
||||||
|
|
||||||
|
cleanup := func() {
|
||||||
|
_ = os.Remove(absInsidePath)
|
||||||
|
_ = os.Remove(absOutsidePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the absolute symlinks are cleaned up from any previous runs
|
||||||
|
cleanup()
|
||||||
|
|
||||||
|
require.NoError(t, os.Symlink(filepath.Join(absolute, "path", "to", "the", "file.txt"), absInsidePath))
|
||||||
|
require.NoError(t, os.Symlink(filepath.Join(absolute, "somewhere", "outside.txt"), absOutsidePath))
|
||||||
|
|
||||||
|
t.Cleanup(cleanup)
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
cwd string
|
||||||
|
root string
|
||||||
|
base string
|
||||||
|
input string
|
||||||
|
expectedRealPath string
|
||||||
|
expectedVirtualPath string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, direct",
|
||||||
|
root: relative,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, direct",
|
||||||
|
root: absolute,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, direct",
|
||||||
|
root: relative,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, direct",
|
||||||
|
root: absolute,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within root...
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, direct, cwd within root",
|
||||||
|
cwd: filepath.Join(relative, "path/to"),
|
||||||
|
root: "../../",
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, direct, cwd within root",
|
||||||
|
cwd: filepath.Join(relative, "path/to"),
|
||||||
|
root: absolute,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, direct, cwd within root",
|
||||||
|
cwd: filepath.Join(relative, "path/to"),
|
||||||
|
root: "../../",
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, direct, cwd within root",
|
||||||
|
cwd: filepath.Join(relative, "path/to"),
|
||||||
|
|
||||||
|
root: absolute,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within symlink root...
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "./",
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: absoluteViaLink,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "./",
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: absoluteViaLink,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within symlink root, request nested within...
|
||||||
|
{
|
||||||
|
name: "relative root, relative nested request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "./path",
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative nested request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absoluteViaLink, "path"),
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs nested request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "./path",
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs nested request, direct, cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absoluteViaLink, "path"),
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within DOUBLE symlink root...
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "./",
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: absoluteViaDoubleLink,
|
||||||
|
input: "path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "./",
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: absoluteViaDoubleLink,
|
||||||
|
input: "/path/to/the/file.txt",
|
||||||
|
expectedRealPath: "path/to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within DOUBLE symlink root, request nested within...
|
||||||
|
{
|
||||||
|
name: "relative root, relative nested request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "./path",
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative nested request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: filepath.Join(absoluteViaDoubleLink, "path"),
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs nested request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "./path",
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs nested request, direct, cwd within (double) symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: filepath.Join(absoluteViaDoubleLink, "path"),
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
// cwd within DOUBLE symlink root, request nested DEEP within...
|
||||||
|
{
|
||||||
|
name: "relative root, relative nested request, direct, cwd deep within (double) symlink root",
|
||||||
|
cwd: filepath.Join(relativeViaDoubleLink, "path", "to"),
|
||||||
|
root: "../",
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative nested request, direct, cwd deep within (double) symlink root",
|
||||||
|
cwd: filepath.Join(relativeViaDoubleLink, "path", "to"),
|
||||||
|
root: filepath.Join(absoluteViaDoubleLink, "path"),
|
||||||
|
input: "to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs nested request, direct, cwd deep within (double) symlink root",
|
||||||
|
cwd: filepath.Join(relativeViaDoubleLink, "path", "to"),
|
||||||
|
root: "../",
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
// note: this is inconsistent with the directory resolver. The real path is essentially the virtual path
|
||||||
|
// in this case for the unindexed resolver, which is not correct.
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs nested request, direct, cwd deep within (double) symlink root",
|
||||||
|
cwd: filepath.Join(relativeViaDoubleLink, "path", "to"),
|
||||||
|
root: filepath.Join(absoluteViaDoubleLink, "path"),
|
||||||
|
input: "/to/the/file.txt",
|
||||||
|
expectedRealPath: "to/the/file.txt",
|
||||||
|
},
|
||||||
|
// link to outside of root cases...
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, abs indirect (outside of root)",
|
||||||
|
root: filepath.Join(relative, "path"),
|
||||||
|
input: "to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, abs indirect (outside of root)",
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, abs indirect (outside of root)",
|
||||||
|
root: filepath.Join(relative, "path"),
|
||||||
|
input: "/to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, abs indirect (outside of root)",
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, relative indirect (outside of root)",
|
||||||
|
root: filepath.Join(relative, "path"),
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, relative indirect (outside of root)",
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, relative indirect (outside of root)",
|
||||||
|
root: filepath.Join(relative, "path"),
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, relative indirect (outside of root)",
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
// link to outside of root cases... cwd within symlink root
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, abs indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "path",
|
||||||
|
input: "to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, abs indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, abs indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "path",
|
||||||
|
input: "/to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, abs indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/abs-outside.txt",
|
||||||
|
expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
expectedVirtualPath: "to/the/abs-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, relative indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "path",
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, relative indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, relative indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: "path",
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, relative indirect (outside of root), cwd within symlink root",
|
||||||
|
cwd: relativeViaLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, relative request, relative indirect (outside of root), cwd within DOUBLE symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "path",
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, relative request, relative indirect (outside of root), cwd within DOUBLE symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relative root, abs request, relative indirect (outside of root), cwd within DOUBLE symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: "path",
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs root, abs request, relative indirect (outside of root), cwd within DOUBLE symlink root",
|
||||||
|
cwd: relativeViaDoubleLink,
|
||||||
|
root: filepath.Join(absolute, "path"),
|
||||||
|
input: "/to/the/rel-outside.txt",
|
||||||
|
//expectedRealPath: filepath.Join(absolute, "/somewhere/outside.txt"),
|
||||||
|
// TODO: the real path is not correct
|
||||||
|
expectedRealPath: "../somewhere/outside.txt",
|
||||||
|
expectedVirtualPath: "to/the/rel-outside.txt",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
|
||||||
|
// we need to mimic a shell, otherwise we won't get a path within a symlink
|
||||||
|
targetPath := filepath.Join(testDir, c.cwd)
|
||||||
|
t.Setenv("PWD", filepath.Clean(targetPath))
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, os.Chdir(targetPath))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
require.NoError(t, os.Chdir(testDir))
|
||||||
|
})
|
||||||
|
|
||||||
|
resolver := NewFromUnindexedDirectory(c.root)
|
||||||
|
require.NotNil(t, resolver)
|
||||||
|
|
||||||
|
refs, err := resolver.FilesByPath(c.input)
|
||||||
|
require.NoError(t, err)
|
||||||
|
if c.expectedRealPath == "" {
|
||||||
|
require.Empty(t, refs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.Len(t, refs, 1)
|
||||||
|
assert.Equal(t, c.expectedRealPath, refs[0].RealPath, "real path different")
|
||||||
|
assert.Equal(t, c.expectedVirtualPath, refs[0].VirtualPath, "virtual path different")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_UnindexedDirectoryResolver_Basic(t *testing.T) {
|
func Test_UnindexedDirectoryResolver_Basic(t *testing.T) {
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
||||||
"github.com/anchore/syft/syft/source"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_KernelCataloger(t *testing.T) {
|
func Test_KernelCataloger(t *testing.T) {
|
||||||
@ -50,7 +49,7 @@ func Test_KernelCataloger(t *testing.T) {
|
|||||||
),
|
),
|
||||||
Licenses: pkg.NewLicenseSet(
|
Licenses: pkg.NewLicenseSet(
|
||||||
pkg.NewLicenseFromLocations("GPL v2",
|
pkg.NewLicenseFromLocations("GPL v2",
|
||||||
source.NewVirtualLocation(
|
file.NewVirtualLocation(
|
||||||
"/lib/modules/6.0.7-301.fc37.x86_64/kernel/drivers/tty/ttynull.ko",
|
"/lib/modules/6.0.7-301.fc37.x86_64/kernel/drivers/tty/ttynull.ko",
|
||||||
"/lib/modules/6.0.7-301.fc37.x86_64/kernel/drivers/tty/ttynull.ko",
|
"/lib/modules/6.0.7-301.fc37.x86_64/kernel/drivers/tty/ttynull.ko",
|
||||||
),
|
),
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/anchore/syft/internal"
|
"github.com/anchore/syft/internal"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/license"
|
"github.com/anchore/syft/syft/license"
|
||||||
"github.com/anchore/syft/syft/source"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLicenseSet_Add(t *testing.T) {
|
func TestLicenseSet_Add(t *testing.T) {
|
||||||
@ -59,15 +58,15 @@ func TestLicenseSet_Add(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "deduplicate licenses with locations",
|
name: "deduplicate licenses with locations",
|
||||||
licenses: []License{
|
licenses: []License{
|
||||||
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
||||||
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
||||||
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "2"})),
|
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "2"})),
|
||||||
},
|
},
|
||||||
want: []License{
|
want: []License{
|
||||||
NewLicenseFromLocations(
|
NewLicenseFromLocations(
|
||||||
"MIT",
|
"MIT",
|
||||||
file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"}),
|
file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "1"}),
|
||||||
file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "2"}),
|
file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "2"}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -75,14 +74,14 @@ func TestLicenseSet_Add(t *testing.T) {
|
|||||||
name: "same licenses with different locations",
|
name: "same licenses with different locations",
|
||||||
licenses: []License{
|
licenses: []License{
|
||||||
NewLicense("MIT"),
|
NewLicense("MIT"),
|
||||||
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "2"})),
|
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "2"})),
|
||||||
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
NewLicenseFromLocations("MIT", file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "1"})),
|
||||||
},
|
},
|
||||||
want: []License{
|
want: []License{
|
||||||
NewLicenseFromLocations(
|
NewLicenseFromLocations(
|
||||||
"MIT",
|
"MIT",
|
||||||
file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "1"}),
|
file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "1"}),
|
||||||
file.NewLocationFromCoordinates(source.Coordinates{RealPath: "/place", FileSystemID: "2"}),
|
file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/place", FileSystemID: "2"}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user