// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package moduleaddrs import ( "fmt" "net/url" "path/filepath" "regexp" ) var forcedRegexp = regexp.MustCompile(`^([A-Za-z0-9]+)::(.+)$`) // This is the minimal set of detectors we need for backward compatibility. // // Do not add any new detectors. All new source types should use the canonical // source address syntax. var detectors = []func(src string) (string, bool, error){ detectGitHub, detectGit, detectBitBucket, detectGCS, detectS3, detectAbsFilePath, } // detectRemoteSourceShorthands recognizes several non-URL strings that // Terraform historically accepted as shorthands for module source addresses, // and converts them each into something more reasonable that specifies // both a source type and a fully-qualified URL. func detectRemoteSourceShorthands(src string) (string, error) { getForce, getSrc := getForcedSourceType(src) // Separate out the subdir if there is one, we don't pass that to detect getSrc, subDir := SplitPackageSubdir(getSrc) u, err := url.Parse(getSrc) if err == nil && u.Scheme != "" { // Valid URL return src, nil } for _, d := range detectors { result, ok, err := d(getSrc) if err != nil { return "", err } if !ok { continue } var detectForce string detectForce, result = getForcedSourceType(result) result, detectSubdir := SplitPackageSubdir(result) // If we have a subdir from the detection, then prepend it to our // requested subdir. if detectSubdir != "" { if subDir != "" { subDir = filepath.Join(detectSubdir, subDir) } else { subDir = detectSubdir } } if subDir != "" { u, err := url.Parse(result) if err != nil { return "", fmt.Errorf("Error parsing URL: %s", err) } u.Path += "//" + subDir // a subdir may contain wildcards, but in order to support them we // have to ensure the path isn't escaped. u.RawPath = u.Path result = u.String() } // Preserve the forced getter if it exists. We try to use the // original set force first, followed by any force set by the // detector. if getForce != "" { result = fmt.Sprintf("%s::%s", getForce, result) } else if detectForce != "" { result = fmt.Sprintf("%s::%s", detectForce, result) } return result, nil } return "", fmt.Errorf("invalid source address: %s", src) } func getForcedSourceType(src string) (string, string) { var forced string if ms := forcedRegexp.FindStringSubmatch(src); ms != nil { forced = ms[1] src = ms[2] } return forced, src }