104 lines
3.0 KiB
Go
104 lines
3.0 KiB
Go
package engine
|
|
|
|
import (
|
|
"io/fs"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func contextsForResolvedSources(resolved *resolvedFilesystemContext, sources []SourceInfo) (map[string]ResourceContext, *Diagnostic) {
|
|
if len(sources) == 0 {
|
|
return nil, nil
|
|
}
|
|
if resolved == nil {
|
|
return nil, nil
|
|
}
|
|
rootPath, basePath := resolved.rootPath, resolved.basePath
|
|
var filesystem fs.FS
|
|
if resolved.native != nil {
|
|
filesystem = resolved.native.filesystem
|
|
}
|
|
var rooted fs.FS
|
|
if filesystem != nil {
|
|
rooted = rootedNativeFS{filesystem: filesystem, root: rootPath}
|
|
} else {
|
|
rooted = rootedHostFS{root: rootPath}
|
|
}
|
|
result := make(map[string]ResourceContext, len(sources))
|
|
for _, acquired := range sources {
|
|
base := basePath
|
|
if acquired.Path != "" {
|
|
if filesystem != nil {
|
|
base = path.Dir(acquired.Path)
|
|
} else {
|
|
base = filepath.Dir(acquired.Path)
|
|
}
|
|
}
|
|
var relative string
|
|
if filesystem != nil {
|
|
if !containsNativePath(rootPath, base) {
|
|
value := importDiagnostic(CodeImportOutsideRoot, "source base is outside the configuration root", nil)
|
|
return nil, &value
|
|
}
|
|
relative = base
|
|
if rootPath != "." {
|
|
relative = strings.TrimPrefix(strings.TrimPrefix(base, rootPath), "/")
|
|
if relative == "" {
|
|
relative = "."
|
|
}
|
|
}
|
|
} else {
|
|
if !containedPath(rootPath, base) {
|
|
value := importDiagnostic(CodeImportOutsideRoot, "source base is outside the configuration root", nil)
|
|
return nil, &value
|
|
}
|
|
var err error
|
|
relative, err = filepath.Rel(rootPath, base)
|
|
if err != nil {
|
|
value := importDiagnostic(CodeImportInvalid, "source base could not be addressed in the configuration root", nil)
|
|
return nil, &value
|
|
}
|
|
relative = filepath.ToSlash(relative)
|
|
}
|
|
result[acquired.ID] = ResourceContext{FS: rooted, BaseDir: relative}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// contextsForAcquiredSources is retained for selected-overlay callers until
|
|
// their request migration. Input acquisition resolves the facts at its own
|
|
// lifecycle boundary and uses contextsForResolvedSources directly.
|
|
func contextsForAcquiredSources(source Source, context *FilesystemContext, baseSource *SourceInfo, sources []SourceInfo) (map[string]ResourceContext, *Diagnostic) {
|
|
if len(sources) == 0 {
|
|
return nil, nil
|
|
}
|
|
if source.kind == sourceNone {
|
|
if context == nil {
|
|
return nil, nil
|
|
}
|
|
resolved, diagnostic := resolveAbsentFilesystemContext(context)
|
|
if diagnostic != nil {
|
|
return nil, diagnostic
|
|
}
|
|
return contextsForResolvedSources(&resolved, sources)
|
|
}
|
|
resolved, diagnostic := resolveFilesystemContext(source, context, parsedSource{source: baseSource}, nil)
|
|
if diagnostic != nil {
|
|
return nil, diagnostic
|
|
}
|
|
return contextsForResolvedSources(&resolved, sources)
|
|
}
|
|
|
|
func mergeResourceContexts(target *map[string]ResourceContext, incoming map[string]ResourceContext) {
|
|
if len(incoming) == 0 {
|
|
return
|
|
}
|
|
if *target == nil {
|
|
*target = make(map[string]ResourceContext, len(incoming))
|
|
}
|
|
for id, context := range incoming {
|
|
(*target)[id] = context
|
|
}
|
|
}
|