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