Files
ConfigKit/internal/engine/source_context.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
}
}