support home dir expansion (#188)

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Alex Goodman 2020-09-28 15:02:21 -04:00 committed by GitHub
parent 2844b9878f
commit 4b78d9a1c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 17 deletions

View File

@ -9,7 +9,8 @@ import (
"fmt"
"strings"
"github.com/anchore/syft/internal/log"
"github.com/mitchellh/go-homedir"
"github.com/spf13/afero"
"github.com/anchore/stereoscope"
@ -48,7 +49,10 @@ type Scope struct {
// NewScope produces a Scope based on userInput like dir: or image:tag
func NewScope(userInput string, o Option) (Scope, func(), error) {
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 {
case directoryScheme:
@ -134,32 +138,39 @@ func (s Scope) Source() interface{} {
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:") {
// 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
// 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)
if err != nil {
// this is not necessarily an error we care a
log.Debugf("unable to detect the scheme from %q: %w", userInput, err)
return unknownScheme, ""
return unknownScheme, "", fmt.Errorf("unable to detect the scheme from %q: %w", userInput, err)
}
if source == image.UnknownSource {
fileMeta, err := fs.Stat(userInput)
dirLocation, err := homedir.Expand(userInput)
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() {
return directoryScheme, userInput
return directoryScheme, dirLocation, nil
}
return unknownScheme, ""
return unknownScheme, "", nil
}
return imageScheme, imageSpec
return imageScheme, imageSpec, nil
}

View File

@ -1,6 +1,7 @@
package scope
import (
"github.com/mitchellh/go-homedir"
"github.com/spf13/afero"
"os"
"testing"
@ -368,30 +369,94 @@ func TestDetectScheme(t *testing.T) {
expectedScheme: directoryScheme,
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 {
t.Run(test.name, func(t *testing.T) {
fs := afero.NewMemMapFs()
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 {
t.Fatalf("failed to create dummy tar: %+v", err)
}
}
imageDetector := func(string) (image.Source, string, error) {
// 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 {
t.Errorf("expected scheme %q , got %q", test.expectedScheme, actualScheme)
}
if actualLocation != test.expectedLocation {
t.Errorf("expected location %q , got %q", test.expectedLocation, actualLocation)
// lean on the users real home directory value
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)
}
})
}