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