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  }