| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: BUSL-1.1 |
| |
| package moduleaddrs |
| |
| import ( |
| "fmt" |
| "path/filepath" |
| "runtime" |
| ) |
| |
| // detectAbsFilePath detects strings that seem like they are trying to be |
| // file paths. |
| // |
| // If the path is absolute then it's transformed into a file:// URL. If it's |
| // relative then we return an error of type *MaybeRelativePathErr, so that |
| // the caller can return a special error message to diagnose that the author |
| // should have written a local source address if they wanted to use a relative |
| // path. |
| // |
| // This should always be the last detector, because unless the input is an |
| // empty string this will always claim everything it's given. |
| func detectAbsFilePath(src string) (string, bool, error) { |
| if len(src) == 0 { |
| return "", false, nil |
| } |
| |
| if !filepath.IsAbs(src) { |
| return "", true, &MaybeRelativePathErr{src} |
| } |
| |
| if runtime.GOOS == "windows" { |
| // Make sure we're using "/" on Windows. URLs are "/"-based. |
| src = filepath.ToSlash(src) |
| return fmt.Sprintf("file://%s", src), true, nil |
| } |
| |
| // Make sure that we don't start with "/" since we add that below. |
| if src[0] == '/' { |
| src = src[1:] |
| } |
| return fmt.Sprintf("file:///%s", src), true, nil |
| } |
| |
| // MaybeRelativePathErr is the error type returned by NormalizePackageAddress |
| // if the source address looks like it might be intended to be a relative |
| // filesystem path but without the required "./" or "../" prefix. |
| // |
| // Specifically, NormalizePackageAddress will return a pointer to this type, |
| // so the error type will be *MaybeRelativePathErr. |
| // |
| // It has a name starting with "Maybe" because in practice we can get here |
| // with any string that isn't recognized as one of the supported schemes: |
| // treating the address as a local filesystem path is our fallback for when |
| // everything else fails, but it could just as easily be a typo in an attempt |
| // to use one of the other schemes and thus not a filesystem path at all. |
| type MaybeRelativePathErr struct { |
| Addr string |
| } |
| |
| func (e *MaybeRelativePathErr) Error() string { |
| return fmt.Sprintf("Terraform cannot detect a supported external module source type for %s", e.Addr) |
| } |