github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/source/scheme.go (about)

     1  package source
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/mitchellh/go-homedir"
     8  	"github.com/spf13/afero"
     9  
    10  	"github.com/anchore/stereoscope/pkg/image"
    11  )
    12  
    13  // Scheme represents the optional prefixed string at the beginning of a user request (e.g. "docker:").
    14  type Scheme string
    15  
    16  const (
    17  	// UnknownScheme is the default scheme
    18  	UnknownScheme Scheme = "UnknownScheme"
    19  	// DirectoryScheme indicates the source being cataloged is a directory on the root filesystem
    20  	DirectoryScheme Scheme = "DirectoryScheme"
    21  	// ImageScheme indicates the source being cataloged is a container image
    22  	ImageScheme Scheme = "ImageScheme"
    23  	// FileScheme indicates the source being cataloged is a single file
    24  	FileScheme Scheme = "FileScheme"
    25  )
    26  
    27  var AllSchemes = []Scheme{
    28  	DirectoryScheme,
    29  	ImageScheme,
    30  	FileScheme,
    31  }
    32  
    33  func DetectScheme(fs afero.Fs, imageDetector sourceDetector, userInput string) (Scheme, image.Source, string, error) {
    34  	switch {
    35  	case strings.HasPrefix(userInput, "dir:"):
    36  		dirLocation, err := homedir.Expand(strings.TrimPrefix(userInput, "dir:"))
    37  		if err != nil {
    38  			return UnknownScheme, image.UnknownSource, "", fmt.Errorf("unable to expand directory path: %w", err)
    39  		}
    40  		return DirectoryScheme, image.UnknownSource, dirLocation, nil
    41  
    42  	case strings.HasPrefix(userInput, "file:"):
    43  		fileLocation, err := homedir.Expand(strings.TrimPrefix(userInput, "file:"))
    44  		if err != nil {
    45  			return UnknownScheme, image.UnknownSource, "", fmt.Errorf("unable to expand directory path: %w", err)
    46  		}
    47  		return FileScheme, image.UnknownSource, fileLocation, nil
    48  	}
    49  
    50  	// try the most specific sources first and move out towards more generic sources.
    51  
    52  	// first: let's try the image detector, which has more scheme parsing internal to stereoscope
    53  	source, imageSpec, err := imageDetector(userInput)
    54  	if err == nil && source != image.UnknownSource {
    55  		return ImageScheme, source, imageSpec, nil
    56  	}
    57  
    58  	// next: let's try more generic sources (dir, file, etc.)
    59  	location, err := homedir.Expand(userInput)
    60  	if err != nil {
    61  		return UnknownScheme, image.UnknownSource, "", fmt.Errorf("unable to expand potential directory path: %w", err)
    62  	}
    63  
    64  	fileMeta, err := fs.Stat(location)
    65  	if err != nil {
    66  		return UnknownScheme, source, "", nil
    67  	}
    68  
    69  	if fileMeta.IsDir() {
    70  		return DirectoryScheme, source, location, nil
    71  	}
    72  
    73  	return FileScheme, source, location, nil
    74  }