mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
The way this all fits together doesn't feel quite right yet since there's a bunch of wrapping layers that aren't really adding anything except indirection between the packages, but this is at least a starting point for child module support. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
73 lines
2.0 KiB
Go
73 lines
2.0 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package addrs
|
|
|
|
import (
|
|
"fmt"
|
|
"io/fs"
|
|
"path"
|
|
)
|
|
|
|
// FIXME: Everything in here should have unit tests
|
|
|
|
// ResolveRelativeModuleSource calculates a new source address from the
|
|
// combination of two other source addresses, if possible.
|
|
func ResolveRelativeModuleSource(a, b ModuleSource) (ModuleSource, error) {
|
|
bLocal, ok := b.(ModuleSourceLocal)
|
|
if !ok {
|
|
return b, nil // non-local source addresses are always absolute
|
|
}
|
|
bRaw := string(bLocal)
|
|
|
|
switch a := a.(type) {
|
|
case ModuleSourceLocal:
|
|
aRaw := string(a)
|
|
new := path.Join(aRaw, bRaw)
|
|
if !isModuleSourceLocal(new) {
|
|
new = "./" + new // ModuleSourceLocal must always have a suitable prefix
|
|
}
|
|
return ModuleSourceLocal(new), nil
|
|
case ModuleSourceRegistry:
|
|
aSub := a.Subdir
|
|
newSub, err := joinModuleSourceSubPath(aSub, bRaw)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid relative path from %s: %w", a.String(), err)
|
|
}
|
|
return ModuleSourceRegistry{
|
|
Package: a.Package,
|
|
Subdir: newSub,
|
|
}, nil
|
|
case ModuleSourceRemote:
|
|
aSub := a.Subdir
|
|
newSub, err := joinModuleSourceSubPath(aSub, bRaw)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid relative path from %s: %w", a.String(), err)
|
|
}
|
|
return ModuleSourceRemote{
|
|
Package: a.Package,
|
|
Subdir: newSub,
|
|
}, nil
|
|
default:
|
|
// Should not get here, because the cases above should cover all
|
|
// of the implementations of [ModuleSource].
|
|
panic(fmt.Sprintf("unsupported ModuleSource type %T", a))
|
|
}
|
|
}
|
|
|
|
func joinModuleSourceSubPath(subPath, rel string) (string, error) {
|
|
new := path.Join(subPath, rel)
|
|
if new == "." {
|
|
return "", nil // the root of the package
|
|
}
|
|
// If subPath was valid then "." and ".." segments can only appear
|
|
// if "rel" has too many "../" segments, causing it to "escape" from
|
|
// its package root.
|
|
if !fs.ValidPath(new) {
|
|
return "", fmt.Errorf("relative path %s has too many \"../\" segments", rel)
|
|
}
|
|
return new, nil
|
|
}
|