github.com/remind101/go-getter@v0.0.0-20180809191950-4bda8fa99001/detect.go (about)

     1  package getter
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  
     7  	"github.com/hashicorp/go-getter/helper/url"
     8  )
     9  
    10  // Detector defines the interface that an invalid URL or a URL with a blank
    11  // scheme is passed through in order to determine if its shorthand for
    12  // something else well-known.
    13  type Detector interface {
    14  	// Detect will detect whether the string matches a known pattern to
    15  	// turn it into a proper URL.
    16  	Detect(string, string) (string, bool, error)
    17  }
    18  
    19  // Detectors is the list of detectors that are tried on an invalid URL.
    20  // This is also the order they're tried (index 0 is first).
    21  var Detectors []Detector
    22  
    23  func init() {
    24  	Detectors = []Detector{
    25  		new(GitHubDetector),
    26  		new(BitBucketDetector),
    27  		new(S3Detector),
    28  		new(FileDetector),
    29  	}
    30  }
    31  
    32  // Detect turns a source string into another source string if it is
    33  // detected to be of a known pattern.
    34  //
    35  // The third parameter should be the list of detectors to use in the
    36  // order to try them. If you don't want to configure this, just use
    37  // the global Detectors variable.
    38  //
    39  // This is safe to be called with an already valid source string: Detect
    40  // will just return it.
    41  func Detect(src string, pwd string, ds []Detector) (string, error) {
    42  	getForce, getSrc := getForcedGetter(src)
    43  
    44  	// Separate out the subdir if there is one, we don't pass that to detect
    45  	getSrc, subDir := SourceDirSubdir(getSrc)
    46  
    47  	u, err := url.Parse(getSrc)
    48  	if err == nil && u.Scheme != "" {
    49  		// Valid URL
    50  		return src, nil
    51  	}
    52  
    53  	for _, d := range ds {
    54  		result, ok, err := d.Detect(getSrc, pwd)
    55  		if err != nil {
    56  			return "", err
    57  		}
    58  		if !ok {
    59  			continue
    60  		}
    61  
    62  		var detectForce string
    63  		detectForce, result = getForcedGetter(result)
    64  		result, detectSubdir := SourceDirSubdir(result)
    65  
    66  		// If we have a subdir from the detection, then prepend it to our
    67  		// requested subdir.
    68  		if detectSubdir != "" {
    69  			if subDir != "" {
    70  				subDir = filepath.Join(detectSubdir, subDir)
    71  			} else {
    72  				subDir = detectSubdir
    73  			}
    74  		}
    75  
    76  		if subDir != "" {
    77  			u, err := url.Parse(result)
    78  			if err != nil {
    79  				return "", fmt.Errorf("Error parsing URL: %s", err)
    80  			}
    81  			u.Path += "//" + subDir
    82  
    83  			// a subdir may contain wildcards, but in order to support them we
    84  			// have to ensure the path isn't escaped.
    85  			u.RawPath = u.Path
    86  
    87  			result = u.String()
    88  		}
    89  
    90  		// Preserve the forced getter if it exists. We try to use the
    91  		// original set force first, followed by any force set by the
    92  		// detector.
    93  		if getForce != "" {
    94  			result = fmt.Sprintf("%s::%s", getForce, result)
    95  		} else if detectForce != "" {
    96  			result = fmt.Sprintf("%s::%s", detectForce, result)
    97  		}
    98  
    99  		return result, nil
   100  	}
   101  
   102  	return "", fmt.Errorf("invalid source string: %s", src)
   103  }