mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
support home dir expansion (#188)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
2844b9878f
commit
4b78d9a1c0
@ -9,7 +9,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/mitchellh/go-homedir"
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope"
|
"github.com/anchore/stereoscope"
|
||||||
@ -48,7 +49,10 @@ type Scope struct {
|
|||||||
// NewScope produces a Scope based on userInput like dir: or image:tag
|
// NewScope produces a Scope based on userInput like dir: or image:tag
|
||||||
func NewScope(userInput string, o Option) (Scope, func(), error) {
|
func NewScope(userInput string, o Option) (Scope, func(), error) {
|
||||||
fs := afero.NewOsFs()
|
fs := afero.NewOsFs()
|
||||||
parsedScheme, location := detectScheme(fs, image.DetectSource, userInput)
|
parsedScheme, location, err := detectScheme(fs, image.DetectSource, userInput)
|
||||||
|
if err != nil {
|
||||||
|
return Scope{}, func() {}, fmt.Errorf("unable to parse input=%q: %w", userInput, err)
|
||||||
|
}
|
||||||
|
|
||||||
switch parsedScheme {
|
switch parsedScheme {
|
||||||
case directoryScheme:
|
case directoryScheme:
|
||||||
@ -134,32 +138,39 @@ func (s Scope) Source() interface{} {
|
|||||||
|
|
||||||
type sourceDetector func(string) (image.Source, string, error)
|
type sourceDetector func(string) (image.Source, string, error)
|
||||||
|
|
||||||
func detectScheme(fs afero.Fs, imageDetector sourceDetector, userInput string) (scheme, string) {
|
func detectScheme(fs afero.Fs, imageDetector sourceDetector, userInput string) (scheme, string, error) {
|
||||||
if strings.HasPrefix(userInput, "dir:") {
|
if strings.HasPrefix(userInput, "dir:") {
|
||||||
// blindly trust the user's scheme
|
// blindly trust the user's scheme
|
||||||
return directoryScheme, strings.TrimPrefix(userInput, "dir:")
|
dirLocation, err := homedir.Expand(strings.TrimPrefix(userInput, "dir:"))
|
||||||
|
if err != nil {
|
||||||
|
return unknownScheme, "", fmt.Errorf("unable to expand directory path: %w", err)
|
||||||
|
}
|
||||||
|
return directoryScheme, dirLocation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// we should attempt to let stereoscope determine what the source is first --just because the source is a valid directory
|
// we should attempt to let stereoscope determine what the source is first --just because the source is a valid directory
|
||||||
// doesn't mean we yet know if it is an OCI layout directory (to be treated as an image) or if it is a generic filesystem directory.
|
// doesn't mean we yet know if it is an OCI layout directory (to be treated as an image) or if it is a generic filesystem directory.
|
||||||
source, imageSpec, err := imageDetector(userInput)
|
source, imageSpec, err := imageDetector(userInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// this is not necessarily an error we care a
|
return unknownScheme, "", fmt.Errorf("unable to detect the scheme from %q: %w", userInput, err)
|
||||||
log.Debugf("unable to detect the scheme from %q: %w", userInput, err)
|
|
||||||
return unknownScheme, ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if source == image.UnknownSource {
|
if source == image.UnknownSource {
|
||||||
fileMeta, err := fs.Stat(userInput)
|
dirLocation, err := homedir.Expand(userInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return unknownScheme, ""
|
return unknownScheme, "", fmt.Errorf("unable to expand potential directory path: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileMeta, err := fs.Stat(dirLocation)
|
||||||
|
if err != nil {
|
||||||
|
return unknownScheme, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileMeta.IsDir() {
|
if fileMeta.IsDir() {
|
||||||
return directoryScheme, userInput
|
return directoryScheme, dirLocation, nil
|
||||||
}
|
}
|
||||||
return unknownScheme, ""
|
return unknownScheme, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageScheme, imageSpec
|
return imageScheme, imageSpec, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package scope
|
package scope
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
@ -368,30 +369,94 @@ func TestDetectScheme(t *testing.T) {
|
|||||||
expectedScheme: directoryScheme,
|
expectedScheme: directoryScheme,
|
||||||
expectedLocation: ".",
|
expectedLocation: ".",
|
||||||
},
|
},
|
||||||
|
// we should support tilde expansion
|
||||||
|
{
|
||||||
|
name: "tilde-expansion-image-implicit",
|
||||||
|
userInput: "~/some-path",
|
||||||
|
detection: detectorResult{
|
||||||
|
src: image.OciDirectorySource,
|
||||||
|
ref: "~/some-path",
|
||||||
|
},
|
||||||
|
expectedScheme: imageScheme,
|
||||||
|
expectedLocation: "~/some-path",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tilde-expansion-dir-implicit",
|
||||||
|
userInput: "~/some-path",
|
||||||
|
detection: detectorResult{
|
||||||
|
src: image.UnknownSource,
|
||||||
|
ref: "",
|
||||||
|
},
|
||||||
|
dirs: []string{"~/some-path"},
|
||||||
|
expectedScheme: directoryScheme,
|
||||||
|
expectedLocation: "~/some-path",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tilde-expansion-dir-explicit-exists",
|
||||||
|
userInput: "dir:~/some-path",
|
||||||
|
dirs: []string{"~/some-path"},
|
||||||
|
expectedScheme: directoryScheme,
|
||||||
|
expectedLocation: "~/some-path",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tilde-expansion-dir-explicit-dne",
|
||||||
|
userInput: "dir:~/some-path",
|
||||||
|
expectedScheme: directoryScheme,
|
||||||
|
expectedLocation: "~/some-path",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tilde-expansion-dir-implicit-dne",
|
||||||
|
userInput: "~/some-path",
|
||||||
|
expectedScheme: unknownScheme,
|
||||||
|
expectedLocation: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
fs := afero.NewMemMapFs()
|
fs := afero.NewMemMapFs()
|
||||||
|
|
||||||
for _, p := range test.dirs {
|
for _, p := range test.dirs {
|
||||||
err := fs.Mkdir(p, os.ModePerm)
|
expandedExpectedLocation, err := homedir.Expand(p)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to expand path=%q: %+v", p, err)
|
||||||
|
}
|
||||||
|
err = fs.Mkdir(expandedExpectedLocation, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create dummy tar: %+v", err)
|
t.Fatalf("failed to create dummy tar: %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imageDetector := func(string) (image.Source, string, error) {
|
imageDetector := func(string) (image.Source, string, error) {
|
||||||
return test.detection.src, test.detection.ref, test.detection.err
|
// lean on the users real home directory value
|
||||||
|
switch test.detection.src {
|
||||||
|
case image.OciDirectorySource, image.DockerTarballSource, image.OciTarballSource:
|
||||||
|
expandedExpectedLocation, err := homedir.Expand(test.expectedLocation)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to expand path=%q: %+v", test.expectedLocation, err)
|
||||||
|
}
|
||||||
|
return test.detection.src, expandedExpectedLocation, test.detection.err
|
||||||
|
default:
|
||||||
|
return test.detection.src, test.detection.ref, test.detection.err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actualScheme, actualLocation := detectScheme(fs, imageDetector, test.userInput)
|
actualScheme, actualLocation, err := detectScheme(fs, imageDetector, test.userInput)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected err : %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if actualScheme != test.expectedScheme {
|
if actualScheme != test.expectedScheme {
|
||||||
t.Errorf("expected scheme %q , got %q", test.expectedScheme, actualScheme)
|
t.Errorf("expected scheme %q , got %q", test.expectedScheme, actualScheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
if actualLocation != test.expectedLocation {
|
// lean on the users real home directory value
|
||||||
t.Errorf("expected location %q , got %q", test.expectedLocation, actualLocation)
|
expandedExpectedLocation, err := homedir.Expand(test.expectedLocation)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to expand path=%q: %+v", test.expectedLocation, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actualLocation != expandedExpectedLocation {
|
||||||
|
t.Errorf("expected location %q , got %q", expandedExpectedLocation, actualLocation)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user