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 } }