github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/getmodules/file_detector.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package getmodules 5 6 import ( 7 "fmt" 8 "path/filepath" 9 "runtime" 10 ) 11 12 // fileDetector is a replacement for go-getter's own file detector which 13 // better meets Terraform's needs: specifically, it rejects relative filesystem 14 // paths with a somewhat-decent error message. 15 // 16 // This is a replacement for some historical hackery we did where we tried to 17 // avoid calling into go-getter altogether in this situation. This is, 18 // therefore, a copy of getter.FileDetector but with the "not absolute path" 19 // case replaced with a similar result as Terraform's old heuristic would've 20 // returned: a custom error type that the caller can react to in order to 21 // produce a hint error message if desired. 22 type fileDetector struct{} 23 24 func (d *fileDetector) Detect(src, pwd string) (string, bool, error) { 25 if len(src) == 0 { 26 return "", false, nil 27 } 28 29 if !filepath.IsAbs(src) { 30 return "", true, &MaybeRelativePathErr{src} 31 } 32 33 return fmtFileURL(src), true, nil 34 } 35 36 func fmtFileURL(path string) string { 37 if runtime.GOOS == "windows" { 38 // Make sure we're using "/" on Windows. URLs are "/"-based. 39 path = filepath.ToSlash(path) 40 return fmt.Sprintf("file://%s", path) 41 } 42 43 // Make sure that we don't start with "/" since we add that below. 44 if path[0] == '/' { 45 path = path[1:] 46 } 47 return fmt.Sprintf("file:///%s", path) 48 } 49 50 // MaybeRelativePathErr is the error type returned by NormalizePackageAddress 51 // if the source address looks like it might be intended to be a relative 52 // filesystem path but without the required "./" or "../" prefix. 53 // 54 // Specifically, NormalizePackageAddress will return a pointer to this type, 55 // so the error type will be *MaybeRelativePathErr. 56 // 57 // It has a name starting with "Maybe" because in practice we can get here 58 // with any string that isn't recognized as one of the supported schemes: 59 // treating the address as a local filesystem path is our fallback for when 60 // everything else fails, but it could just as easily be a typo in an attempt 61 // to use one of the other schemes and thus not a filesystem path at all. 62 type MaybeRelativePathErr struct { 63 Addr string 64 } 65 66 func (e *MaybeRelativePathErr) Error() string { 67 return fmt.Sprintf("Terraform cannot detect a supported external module source type for %s", e.Addr) 68 }