mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
refactor(fs): use underlyingPath to determine virtual files more reliably (#9302)
Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io>
This commit is contained in:
@@ -28,7 +28,7 @@ type file struct {
|
||||
}
|
||||
|
||||
func (f *file) isVirtual() bool {
|
||||
return len(f.data) != 0 || f.stat.IsDir()
|
||||
return f.underlyingPath == ""
|
||||
}
|
||||
|
||||
func (f *file) Open(name string) (fs.File, error) {
|
||||
@@ -59,7 +59,7 @@ func (f *file) open() (fs.File, error) {
|
||||
fileStat: f.stat,
|
||||
entry: entries,
|
||||
}, nil
|
||||
case len(f.data) != 0: // Virtual file
|
||||
case f.isVirtual(): // Virtual file
|
||||
return &openMapFile{
|
||||
path: f.stat.name,
|
||||
file: f,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mapfs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
@@ -98,7 +99,7 @@ func (m *FS) FilterFunc(fn func(path string, d fs.DirEntry) (bool, error)) (*FS,
|
||||
return xerrors.Errorf("unable to get %s: %w", path, err)
|
||||
}
|
||||
// Virtual file
|
||||
if f.underlyingPath == "" {
|
||||
if f.isVirtual() {
|
||||
return newFS.WriteVirtualFile(path, f.data, f.stat.mode)
|
||||
}
|
||||
return newFS.WriteFile(path, f.underlyingPath)
|
||||
@@ -197,6 +198,9 @@ func (m *FS) Open(name string) (fs.File, error) {
|
||||
|
||||
// WriteFile creates a mapping between path and underlyingPath.
|
||||
func (m *FS) WriteFile(path, underlyingPath string) error {
|
||||
if underlyingPath == "" {
|
||||
return errors.New("underlying path must not be empty")
|
||||
}
|
||||
return m.root.WriteFile(cleanPath(path), underlyingPath)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,12 @@ var (
|
||||
isDir: false,
|
||||
size: 7,
|
||||
}
|
||||
emptyVirtualFileInfo = fileInfo{
|
||||
name: "empty-virtual.txt",
|
||||
fileMode: 0o600,
|
||||
isDir: false,
|
||||
size: 0,
|
||||
}
|
||||
cdirFileInfo = fileInfo{
|
||||
name: "c",
|
||||
fileMode: fs.FileMode(0o700) | fs.ModeDir,
|
||||
@@ -57,6 +63,7 @@ func initFS(t *testing.T) *mapfs.FS {
|
||||
require.NoError(t, fsys.WriteFile("a/b/c/c.txt", "testdata/c.txt"))
|
||||
require.NoError(t, fsys.WriteFile("a/b/c/.dotfile", "testdata/dotfile"))
|
||||
require.NoError(t, fsys.WriteVirtualFile("a/b/c/virtual.txt", []byte("virtual"), 0o600))
|
||||
require.NoError(t, fsys.WriteVirtualFile("a/b/c/empty-virtual.txt", []byte{}, 0o600))
|
||||
return fsys
|
||||
}
|
||||
|
||||
@@ -119,6 +126,12 @@ func TestFS_Stat(t *testing.T) {
|
||||
want: virtualFileInfo,
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "empty virtual file",
|
||||
filePath: "a/b/c/empty-virtual.txt",
|
||||
want: emptyVirtualFileInfo,
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "dir",
|
||||
filePath: "a/b/c",
|
||||
@@ -142,6 +155,55 @@ func TestFS_Stat(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFS_WriteFile(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
dstPath string
|
||||
underlyingPath string
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "write file",
|
||||
dstPath: "hello.txt",
|
||||
underlyingPath: "testdata/hello.txt",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "write file to non-existent dir",
|
||||
dstPath: "test/hello.txt",
|
||||
underlyingPath: "testdata/hello.txt",
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "write file to existent dir",
|
||||
dstPath: "subdir/hello.txt",
|
||||
underlyingPath: "testdata/hello.txt",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "empty underlying path",
|
||||
dstPath: "copy/empty.txt",
|
||||
underlyingPath: "",
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fsys := mapfs.New()
|
||||
require.NoError(t, fsys.MkdirAll("subdir", 0o700))
|
||||
|
||||
err := fsys.WriteFile(tt.dstPath, tt.underlyingPath)
|
||||
tt.wantErr(t, err)
|
||||
|
||||
if err == nil {
|
||||
_, statErr := fsys.Stat(tt.dstPath)
|
||||
assert.NoError(t, statErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFS_ReadDir(t *testing.T) {
|
||||
type dirEntry struct {
|
||||
name string
|
||||
@@ -211,6 +273,13 @@ func TestFS_ReadDir(t *testing.T) {
|
||||
size: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty-virtual.txt",
|
||||
fileMode: 0o600,
|
||||
isDir: false,
|
||||
size: 0,
|
||||
fileInfo: emptyVirtualFileInfo,
|
||||
},
|
||||
{
|
||||
name: "virtual.txt",
|
||||
fileMode: 0o600,
|
||||
@@ -278,6 +347,15 @@ func TestFS_Open(t *testing.T) {
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "empty virtual file",
|
||||
filePath: "a/b/c/empty-virtual.txt",
|
||||
want: file{
|
||||
fileInfo: emptyVirtualFileInfo,
|
||||
body: "",
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "dir",
|
||||
filePath: "a/b/c",
|
||||
@@ -337,6 +415,12 @@ func TestFS_ReadFile(t *testing.T) {
|
||||
want: "virtual",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "empty virtual file",
|
||||
filePath: "a/b/c/empty-virtual.txt",
|
||||
want: "",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "no such file",
|
||||
filePath: "nosuch.txt",
|
||||
@@ -385,6 +469,7 @@ func TestFS_Glob(t *testing.T) {
|
||||
pattern: "*/b/c/*.txt",
|
||||
want: []string{
|
||||
"a/b/c/c.txt",
|
||||
"a/b/c/empty-virtual.txt",
|
||||
"a/b/c/virtual.txt",
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
@@ -432,6 +517,11 @@ func TestFS_Remove(t *testing.T) {
|
||||
path: "a/b/c/virtual.txt",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "empty virtual file",
|
||||
path: "a/b/c/empty-virtual.txt",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "empty dir",
|
||||
path: "a/b/empty",
|
||||
@@ -481,6 +571,8 @@ func TestFS_RemoveAll(t *testing.T) {
|
||||
require.ErrorIs(t, err, fs.ErrNotExist)
|
||||
_, err = fsys.Stat("a/b/c/virtual.txt")
|
||||
require.ErrorIs(t, err, fs.ErrNotExist)
|
||||
_, err = fsys.Stat("a/b/c/empty-virtual.txt")
|
||||
require.ErrorIs(t, err, fs.ErrNotExist)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user