Consolidate selected overlay acquisition
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Consolidation Implementation Plan
|
# Consolidation Implementation Plan
|
||||||
|
|
||||||
Status: in progress. Stages 1 through 8 are complete; follow Stage 9 through Stage 20 in order.
|
Status: in progress. Stages 1 through 9 are complete; follow Stage 10 through Stage 20 in order.
|
||||||
The target executor is a Luna coding agent working through one end-to-end sprint.
|
The target executor is a Luna coding agent working through one end-to-end sprint.
|
||||||
|
|
||||||
## Authority, Baseline, And Execution
|
## Authority, Baseline, And Execution
|
||||||
@@ -413,7 +413,7 @@ sources. Migrated the ordinary backfill and reordered-source context test. The
|
|||||||
selected-overlay adapters remain for Stage 9. Focused context/acquisition tests,
|
selected-overlay adapters remain for Stage 9. Focused context/acquisition tests,
|
||||||
`GOTOOLCHAIN=local GOPROXY=off go test ./...`, and `git diff --check` passed.
|
`GOTOOLCHAIN=local GOPROXY=off go test ./...`, and `git diff --check` passed.
|
||||||
|
|
||||||
## Stage 9 — Migrate Selected Overlays Without Merging Their Semantics
|
## Stage 9 — Migrate Selected Overlays Without Merging Their Semantics (Complete)
|
||||||
|
|
||||||
**Owners:** engine `selected_overlay.go`, ordinary `applyInputLayers`, and
|
**Owners:** engine `selected_overlay.go`, ordinary `applyInputLayers`, and
|
||||||
`assembleLayeredInput`.
|
`assembleLayeredInput`.
|
||||||
@@ -445,6 +445,14 @@ ordinary and independent layered overlay semantics remain distinct. Run A when
|
|||||||
buildable; carry any genuine remaining migration dependencies to the next
|
buildable; carry any genuine remaining migration dependencies to the next
|
||||||
integration opportunity instead of adding scaffolding or stopping the sprint.
|
integration opportunity instead of adding scaffolding or stopping the sprint.
|
||||||
|
|
||||||
|
Progress notes (2026-10-25): introduced the named overlay request and migrated
|
||||||
|
ordinary and independent layered overlay acquisition to resolved facts plus
|
||||||
|
explicit access. Replaced the variadic compatibility branch with the existing
|
||||||
|
collection-aware path, removed old context adapters, and retained overlay
|
||||||
|
validation timing, source evidence, budgets, version protection, and close
|
||||||
|
reporting. Validation group A, consumer examples, the full Go suite, and
|
||||||
|
`git diff --check` passed.
|
||||||
|
|
||||||
## Stage 10 — Give Import Responsibilities Focused Files
|
## Stage 10 — Give Import Responsibilities Focused Files
|
||||||
|
|
||||||
**Owners:** engine `imports.go` and new `import_acquisition.go`,
|
**Owners:** engine `imports.go` and new `import_acquisition.go`,
|
||||||
|
|||||||
@@ -12,17 +12,20 @@ func validateFilesystemContext(source Source, context *FilesystemContext, main p
|
|||||||
return validateAbsentHostFilesystemContext(context)
|
return validateAbsentHostFilesystemContext(context)
|
||||||
}
|
}
|
||||||
if nativeContext(source, context) {
|
if nativeContext(source, context) {
|
||||||
access, basePath, mainPath, diagnostic := nativeFilesystemAccess(source, context)
|
resolved, diagnostic := resolveNativeFilesystemContext(source, context)
|
||||||
if diagnostic != nil {
|
if diagnostic != nil {
|
||||||
return diagnostic
|
return diagnostic
|
||||||
}
|
}
|
||||||
return validateNativeDirectories(access, basePath, mainPath)
|
return validateResolvedFilesystemDirectories(resolved)
|
||||||
}
|
}
|
||||||
rootPath, _, _, diagnostic := importFilesystem(source, context, main)
|
resolved, diagnostic := resolveHostFilesystemContext(source, context, main, nil)
|
||||||
if diagnostic != nil {
|
if diagnostic != nil {
|
||||||
return diagnostic
|
return diagnostic
|
||||||
}
|
}
|
||||||
root, err := os.OpenRoot(rootPath)
|
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
|
||||||
|
return diagnostic
|
||||||
|
}
|
||||||
|
root, err := os.OpenRoot(resolved.rootPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
value := globFilesystemDiagnostic(err, "configuration root could not be opened", Location{})
|
value := globFilesystemDiagnostic(err, "configuration root could not be opened", Location{})
|
||||||
value.Primary = nil
|
value.Primary = nil
|
||||||
@@ -133,52 +136,6 @@ func nativeContext(source Source, context *FilesystemContext) bool {
|
|||||||
return source.kind == sourceFilesystem || context != nil && context.FS != nil
|
return source.kind == sourceFilesystem || context != nil && context.FS != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nativeFilesystemAccess resolves namespace context without opening caller
|
|
||||||
// resources. File inputs always derive their base from the selected file.
|
|
||||||
func nativeFilesystemAccess(source Source, context *FilesystemContext) (*filesystemAccess, string, string, *Diagnostic) {
|
|
||||||
resolved, diagnostic := resolveNativeFilesystemContext(source, context)
|
|
||||||
if diagnostic != nil {
|
|
||||||
return nil, "", "", diagnostic
|
|
||||||
}
|
|
||||||
access, err := openResolvedFilesystemAccess(resolved)
|
|
||||||
if err != nil {
|
|
||||||
value := globFilesystemDiagnostic(err, "configuration root could not be opened", Location{})
|
|
||||||
value.Primary = nil
|
|
||||||
return nil, "", "", &value
|
|
||||||
}
|
|
||||||
return access, resolved.basePath, resolved.mainPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateNativeDirectories(access *filesystemAccess, basePath, mainPath string) *Diagnostic {
|
|
||||||
if !access.contains(basePath) || mainPath != "" && !access.contains(mainPath) {
|
|
||||||
value := importDiagnostic(CodeImportOutsideRoot, "selected source and import base must stay inside the configuration root", nil)
|
|
||||||
return &value
|
|
||||||
}
|
|
||||||
for _, directory := range []string{access.rootPath, basePath} {
|
|
||||||
info, err := access.stat(directory)
|
|
||||||
if err != nil || !info.IsDir() {
|
|
||||||
value := importDiagnostic(CodeImportInvalid, "configuration root and import base must be directories", nil)
|
|
||||||
return &value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func importFilesystem(source Source, context *FilesystemContext, main parsedSource) (rootPath, basePath, mainPath string, diagnostic *Diagnostic) {
|
|
||||||
if main.source == nil || main.document == nil {
|
|
||||||
value := importDiagnostic(CodeImportInvalid, "imports require a selected configuration source", nil)
|
|
||||||
return "", "", "", &value
|
|
||||||
}
|
|
||||||
resolved, diagnostic := resolveHostFilesystemContext(source, context, main, nil)
|
|
||||||
if diagnostic != nil {
|
|
||||||
return "", "", "", diagnostic
|
|
||||||
}
|
|
||||||
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
|
|
||||||
return "", "", "", diagnostic
|
|
||||||
}
|
|
||||||
return resolved.rootPath, resolved.basePath, resolved.mainPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func canonicalExistingPath(name string) (string, error) {
|
func canonicalExistingPath(name string) (string, error) {
|
||||||
absolute, err := filepath.Abs(name)
|
absolute, err := filepath.Abs(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ func resolveAbsentFilesystemContext(context *FilesystemContext) (resolvedFilesys
|
|||||||
return resolvedFilesystemContext{}, &value
|
return resolvedFilesystemContext{}, &value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !containedPath(rootPath, basePath) {
|
||||||
|
value := importDiagnostic(CodeImportOutsideRoot, "selected source and import base must stay inside the configuration root", nil)
|
||||||
|
return resolvedFilesystemContext{}, &value
|
||||||
|
}
|
||||||
return resolvedFilesystemContext{rootPath: rootPath, basePath: basePath}, nil
|
return resolvedFilesystemContext{rootPath: rootPath, basePath: basePath}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,14 +97,29 @@ func applyInputLayers(source Source, filesystem *FilesystemContext, overlay stri
|
|||||||
return input, diagnostics
|
return input, diagnostics
|
||||||
}
|
}
|
||||||
assembly := newAssemblyAccumulator(composition)
|
assembly := newAssemblyAccumulator(composition)
|
||||||
input.sources, diagnostics = loadSelectedOverlayIntoWithVersion(
|
resolved, diagnostic := resolveOrdinaryOverlayFilesystem(source, filesystem, input.parsed, input.resolvedFilesystem)
|
||||||
source, filesystem, input.parsed, assembly, input.sources,
|
if diagnostic != nil {
|
||||||
overlay, protectionRule, defaultImportLimits(), input.versionState, policy,
|
return input, []Diagnostic{*diagnostic}
|
||||||
)
|
}
|
||||||
|
if source.kind != sourceNone || nativeContext(source, filesystem) {
|
||||||
|
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
|
||||||
|
return input, []Diagnostic{*diagnostic}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request := selectedOverlayRequest{
|
||||||
|
name: overlay, filesystem: resolved, protectionRule: protectionRule,
|
||||||
|
sequencePolicy: policy, limits: defaultImportLimits(), versionState: input.versionState,
|
||||||
|
}
|
||||||
|
access, diagnostic := openSelectedOverlayAccess(resolved)
|
||||||
|
if diagnostic != nil {
|
||||||
|
return input, []Diagnostic{*diagnostic}
|
||||||
|
}
|
||||||
|
input.sources, diagnostics = loadSelectedOverlay(request, access, assembly, input.sources)
|
||||||
if len(diagnostics) != 0 {
|
if len(diagnostics) != 0 {
|
||||||
return input, diagnostics
|
return input, diagnostics
|
||||||
}
|
}
|
||||||
contexts, diagnostic := contextsForAcquiredSources(source, filesystem, input.parsed.source, input.sources[len(input.sources)-1:])
|
input.resolvedFilesystem = &resolved
|
||||||
|
contexts, diagnostic := contextsForResolvedSources(&resolved, input.sources[len(input.sources)-1:])
|
||||||
if diagnostic != nil {
|
if diagnostic != nil {
|
||||||
return input, []Diagnostic{*diagnostic}
|
return input, []Diagnostic{*diagnostic}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,17 +192,30 @@ func assembleLayeredInput[T any](request loadRequest[T], input assembledInput, p
|
|||||||
assembly.current.inputBytes = state.accounting.bytes
|
assembly.current.inputBytes = state.accounting.bytes
|
||||||
assembly.current.inputNodes = state.accounting.nodes
|
assembly.current.inputNodes = state.accounting.nodes
|
||||||
if activeOverlay(request.overlay) {
|
if activeOverlay(request.overlay) {
|
||||||
// The selected overlay context is independent of the main input. This
|
if request.overlayFilesystem == nil {
|
||||||
// synthetic descriptor creates no source record or input contribution.
|
return input, append(versionDiagnostics, optionDiagnostic(CodeOptionsInvalid, "selected overlay requires explicit filesystem context"))
|
||||||
selection := Source{kind: sourceBytes}
|
}
|
||||||
selected := parsedSource{document: &document.Node{Kind: document.Mapping}, source: &SourceInfo{}}
|
resolved, diagnostic := resolveAbsentFilesystemContext(request.overlayFilesystem)
|
||||||
|
if diagnostic != nil {
|
||||||
|
return input, append(versionDiagnostics, *diagnostic)
|
||||||
|
}
|
||||||
|
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
|
||||||
|
return input, append(versionDiagnostics, *diagnostic)
|
||||||
|
}
|
||||||
|
overlayRequest := selectedOverlayRequest{
|
||||||
|
name: request.overlay, filesystem: resolved, protectionRule: request.protectionVersion(),
|
||||||
|
sequencePolicy: policy.sequencePolicy, limits: defaultImportLimits(), versionState: input.versionState,
|
||||||
|
}
|
||||||
var diagnostics []Diagnostic
|
var diagnostics []Diagnostic
|
||||||
overlayPolicy := []sequencePolicy{policy.sequencePolicy}
|
access, diagnostic := openSelectedOverlayAccess(resolved)
|
||||||
input.sources, diagnostics = loadSelectedOverlayIntoWithVersion(selection, request.overlayFilesystem, selected, assembly, input.sources, request.overlay, request.protectionVersion(), defaultImportLimits(), input.versionState, overlayPolicy...)
|
if diagnostic != nil {
|
||||||
|
return input, append(versionDiagnostics, *diagnostic)
|
||||||
|
}
|
||||||
|
input.sources, diagnostics = loadSelectedOverlay(overlayRequest, access, assembly, input.sources)
|
||||||
if len(diagnostics) != 0 {
|
if len(diagnostics) != 0 {
|
||||||
return input, append(versionDiagnostics, diagnostics...)
|
return input, append(versionDiagnostics, diagnostics...)
|
||||||
}
|
}
|
||||||
contexts, diagnostic := contextsForAcquiredSources(selection, request.overlayFilesystem, selected.source, input.sources[len(input.sources)-1:])
|
contexts, diagnostic := contextsForResolvedSources(&resolved, input.sources[len(input.sources)-1:])
|
||||||
if diagnostic != nil {
|
if diagnostic != nil {
|
||||||
return input, append(versionDiagnostics, *diagnostic)
|
return input, append(versionDiagnostics, *diagnostic)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,84 +28,51 @@ func validOverlayName(name string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSelectedOverlayDocument(source Source, context *FilesystemContext, main parsedSource, base *composedDocument, sources []SourceInfo, name string, rule *VersionRule, limits importLimits) (*composedDocument, []SourceInfo, []Diagnostic) {
|
type selectedOverlayRequest struct {
|
||||||
assembly := newAssemblyAccumulator(cloneComposedDocument(base))
|
name string
|
||||||
allSources, diagnostics := loadSelectedOverlayInto(source, context, main, assembly, sources, name, rule, limits)
|
filesystem resolvedFilesystemContext
|
||||||
if len(diagnostics) != 0 {
|
protectionRule *VersionRule
|
||||||
return nil, allSources, diagnostics
|
sequencePolicy sequencePolicy
|
||||||
}
|
limits importLimits
|
||||||
return assembly.current, allSources, nil
|
versionState *sourceVersionState
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSelectedOverlayInto(source Source, context *FilesystemContext, main parsedSource, base *assemblyAccumulator, sources []SourceInfo, name string, rule *VersionRule, limits importLimits) ([]SourceInfo, []Diagnostic) {
|
func resolveOrdinaryOverlayFilesystem(source Source, context *FilesystemContext, main parsedSource, existing *resolvedFilesystemContext) (resolvedFilesystemContext, *Diagnostic) {
|
||||||
return loadSelectedOverlayIntoWithVersion(source, context, main, base, sources, name, rule, limits, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadSelectedOverlayIntoWithVersion(source Source, context *FilesystemContext, main parsedSource, base *assemblyAccumulator, sources []SourceInfo, name string, rule *VersionRule, limits importLimits, versionState *sourceVersionState, policies ...sequencePolicy) ([]SourceInfo, []Diagnostic) {
|
|
||||||
var policy sequencePolicy
|
|
||||||
if len(policies) != 0 {
|
|
||||||
policy = policies[0]
|
|
||||||
}
|
|
||||||
if nativeContext(source, context) {
|
|
||||||
access, basePath, mainPath, diagnostic := nativeFilesystemAccess(source, context)
|
|
||||||
if diagnostic != nil {
|
|
||||||
return cloneSourceInfos(sources), []Diagnostic{*diagnostic}
|
|
||||||
}
|
|
||||||
if diagnostic := validateNativeDirectories(access, basePath, mainPath); diagnostic != nil {
|
|
||||||
return cloneSourceInfos(sources), []Diagnostic{*diagnostic}
|
|
||||||
}
|
|
||||||
if len(policies) == 0 {
|
|
||||||
return loadSelectedOverlayWithAccessAndVersion(access, base, sources, name, rule, limits, versionState)
|
|
||||||
}
|
|
||||||
return loadSelectedOverlayWithAccessAndVersion(access, base, sources, name, rule, limits, versionState, policy)
|
|
||||||
}
|
|
||||||
var rootPath string
|
|
||||||
if source.kind == sourceNone {
|
if source.kind == sourceNone {
|
||||||
if context == nil {
|
if context == nil {
|
||||||
value := optionDiagnostic(CodeOptionsInvalid, "NoSource overlays require explicit filesystem context")
|
value := optionDiagnostic(CodeOptionsInvalid, "NoSource overlays require explicit filesystem context")
|
||||||
return cloneSourceInfos(sources), []Diagnostic{value}
|
return resolvedFilesystemContext{}, &value
|
||||||
}
|
|
||||||
var err error
|
|
||||||
rootPath, err = canonicalExistingPath(context.Root)
|
|
||||||
if err != nil {
|
|
||||||
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
|
|
||||||
return cloneSourceInfos(sources), []Diagnostic{value}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var diagnostic *Diagnostic
|
|
||||||
rootPath, _, _, diagnostic = importFilesystem(source, context, main)
|
|
||||||
if diagnostic != nil {
|
|
||||||
return cloneSourceInfos(sources), []Diagnostic{*diagnostic}
|
|
||||||
}
|
}
|
||||||
|
return resolveAbsentFilesystemContext(context)
|
||||||
}
|
}
|
||||||
access, err := openHostAccess(rootPath)
|
if existing != nil {
|
||||||
|
return *existing, nil
|
||||||
|
}
|
||||||
|
return resolveFilesystemContext(source, context, main, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openSelectedOverlayAccess(resolved resolvedFilesystemContext) (*filesystemAccess, *Diagnostic) {
|
||||||
|
access, err := openResolvedFilesystemAccess(resolved)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
value := globFilesystemDiagnostic(err, "configuration root could not be opened for the selected overlay", Location{})
|
value := globFilesystemDiagnostic(err, "configuration root could not be opened for the selected overlay", Location{})
|
||||||
value.Primary = nil
|
value.Primary = nil
|
||||||
return cloneSourceInfos(sources), []Diagnostic{value}
|
return nil, &value
|
||||||
}
|
}
|
||||||
if len(policies) == 0 {
|
return access, nil
|
||||||
return loadSelectedOverlayWithAccessAndVersion(access, base, sources, name, rule, limits, versionState)
|
|
||||||
}
|
|
||||||
return loadSelectedOverlayWithAccessAndVersion(access, base, sources, name, rule, limits, versionState, policy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSelectedOverlayWithAccess(access *filesystemAccess, base *assemblyAccumulator, sources []SourceInfo, name string, rule *VersionRule, limits importLimits) ([]SourceInfo, []Diagnostic) {
|
func loadSelectedOverlay(request selectedOverlayRequest, access *filesystemAccess, base *assemblyAccumulator, sources []SourceInfo) ([]SourceInfo, []Diagnostic) {
|
||||||
return loadSelectedOverlayWithAccessAndVersion(access, base, sources, name, rule, limits, nil)
|
policy := request.sequencePolicy
|
||||||
}
|
rule := request.protectionRule
|
||||||
|
limits := request.limits
|
||||||
func loadSelectedOverlayWithAccessAndVersion(access *filesystemAccess, base *assemblyAccumulator, sources []SourceInfo, name string, rule *VersionRule, limits importLimits, versionState *sourceVersionState, policies ...sequencePolicy) ([]SourceInfo, []Diagnostic) {
|
versionState := request.versionState
|
||||||
var policy sequencePolicy
|
|
||||||
if len(policies) != 0 {
|
|
||||||
policy = policies[0]
|
|
||||||
}
|
|
||||||
closed := false
|
closed := false
|
||||||
defer func() {
|
defer func() {
|
||||||
if !closed {
|
if !closed {
|
||||||
_ = access.close()
|
_ = access.close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
overlayPath := access.join(access.rootPath, "overlays/"+name+".yml")
|
overlayPath := access.join(access.rootPath, "overlays/"+request.name+".yml")
|
||||||
canonical, err := access.canonical(overlayPath)
|
canonical, err := access.canonical(overlayPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
code := CodeOverlayInvalid
|
code := CodeOverlayInvalid
|
||||||
@@ -138,7 +105,7 @@ func loadSelectedOverlayWithAccessAndVersion(access *filesystemAccess, base *ass
|
|||||||
sourceID := "source-" + strconv.Itoa(len(sources)+1)
|
sourceID := "source-" + strconv.Itoa(len(sources)+1)
|
||||||
overlayLocation := &Location{SourceID: sourceID}
|
overlayLocation := &Location{SourceID: sourceID}
|
||||||
kind := SourceKindFile
|
kind := SourceKindFile
|
||||||
label := "overlays/" + name + ".yml"
|
label := "overlays/" + request.name + ".yml"
|
||||||
if access.native != nil {
|
if access.native != nil {
|
||||||
kind = SourceKindFilesystem
|
kind = SourceKindFilesystem
|
||||||
label = access.label + "/" + canonical
|
label = access.label + "/" + canonical
|
||||||
@@ -160,66 +127,44 @@ func loadSelectedOverlayWithAccessAndVersion(access *filesystemAccess, base *ass
|
|||||||
if base.current.inputNodes+nodeCount > limits.nodes {
|
if base.current.inputNodes+nodeCount > limits.nodes {
|
||||||
return sources, []Diagnostic{importDiagnostic(CodeOverlayLimitExceeded, "selected overlay exceeds the aggregate node limit", overlayLocation)}
|
return sources, []Diagnostic{importDiagnostic(CodeOverlayLimitExceeded, "selected overlay exceeds the aggregate node limit", overlayLocation)}
|
||||||
}
|
}
|
||||||
if diagnostics := overlayDirectiveDiagnostics(overlayRoot, Path{}, len(policies) != 0); len(diagnostics) != 0 {
|
if diagnostics := overlayDirectiveDiagnostics(overlayRoot, Path{}, true); len(diagnostics) != 0 {
|
||||||
return sources, diagnostics
|
return sources, diagnostics
|
||||||
}
|
}
|
||||||
var processed sourceVersionProcessingResult
|
var processed sourceVersionProcessingResult
|
||||||
var failures []Diagnostic
|
var failures []Diagnostic
|
||||||
if len(policies) != 0 {
|
if versionState != nil {
|
||||||
if versionState != nil {
|
processed, failures = versionState.processWithDirectiveContext(
|
||||||
processed, failures = versionState.processWithDirectiveContext(
|
overlayRoot, sourceVersionContribution, Path{}, sourceID, placementModeMapping, rootDirectiveContextOverlay,
|
||||||
overlayRoot, sourceVersionContribution, Path{}, sourceID, placementModeMapping, rootDirectiveContextOverlay,
|
)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
processed = processSourceVersionWithDirectiveContext(
|
|
||||||
overlayRoot, rule, sourceVersionContribution, Path{}, sourceVersionModeDefault, rootDirectiveContextOverlay,
|
|
||||||
)
|
|
||||||
failures = processed.diagnostics
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if versionState != nil && versionState.mode != sourceVersionModeDefault {
|
processed = processSourceVersionWithDirectiveContext(
|
||||||
processed, failures = versionState.process(overlayRoot, sourceVersionContribution, Path{}, sourceID, placementModeMapping)
|
overlayRoot, rule, sourceVersionContribution, Path{}, sourceVersionModeDefault, rootDirectiveContextOverlay,
|
||||||
} else {
|
)
|
||||||
processed = sourceVersionProcessingResult{payload: overlayRoot}
|
failures = processed.diagnostics
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if len(failures) != 0 {
|
if len(failures) != 0 {
|
||||||
return sources, failures
|
return sources, failures
|
||||||
}
|
}
|
||||||
overlayPayload := processed.payload
|
overlayPayload := processed.payload
|
||||||
if versionNode := fragmentVersionClaim(overlayPayload, rule); len(policies) == 0 && versionNode != nil {
|
|
||||||
location := publicLocation(versionNode.Location)
|
|
||||||
return sources, []Diagnostic{{
|
|
||||||
Code: CodeOverlayVersion, Severity: SeverityError, Path: rule.Path.clone(),
|
|
||||||
Message: "overlays cannot contribute to or replace the schema-version path", Primary: &location,
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
closeErr := access.close()
|
closeErr := access.close()
|
||||||
closed = true
|
closed = true
|
||||||
if closeErr != nil {
|
if closeErr != nil {
|
||||||
return sources, []Diagnostic{importDiagnostic(CodeImportRead, "configuration root could not be closed after reading the selected overlay", nil)}
|
return sources, []Diagnostic{importDiagnostic(CodeImportRead, "configuration root could not be closed after reading the selected overlay", nil)}
|
||||||
}
|
}
|
||||||
|
|
||||||
var overlayDiagnostics []Diagnostic
|
overlayDiagnostics := base.applyOverlayWithCollectionPolicy(overlayPayload, nil, collectionPolicyScope{}, nil, LayerOverlay, policy, processed.sequences)
|
||||||
if len(policies) != 0 {
|
|
||||||
overlayDiagnostics = base.applyOverlayWithCollectionPolicy(overlayPayload, nil, collectionPolicyScope{}, nil, LayerOverlay, policy, processed.sequences)
|
|
||||||
} else {
|
|
||||||
overlayDiagnostics = base.applyOverlay(overlayPayload, nil, nil, LayerOverlay)
|
|
||||||
}
|
|
||||||
if len(overlayDiagnostics) != 0 {
|
if len(overlayDiagnostics) != 0 {
|
||||||
return sources, overlayDiagnostics
|
return sources, overlayDiagnostics
|
||||||
}
|
}
|
||||||
if len(policies) != 0 {
|
// The selected overlay retains one application with the actual item
|
||||||
// The selected overlay retains one application with the actual item
|
// assignments. Raw list indexes cannot identify an upsert's destination.
|
||||||
// assignments. Raw list indexes cannot identify an upsert's destination.
|
application := base.current.applications[len(base.current.applications)-1]
|
||||||
application := base.current.applications[len(base.current.applications)-1]
|
if node := versionClaimFromApplication(application, rule); node != nil {
|
||||||
if node := versionClaimFromApplication(application, rule); node != nil {
|
location := publicLocation(node.Location)
|
||||||
location := publicLocation(node.Location)
|
return sources, []Diagnostic{{
|
||||||
return sources, []Diagnostic{{
|
Code: CodeOverlayVersion, Severity: SeverityError, Path: rule.Path.clone(),
|
||||||
Code: CodeOverlayVersion, Severity: SeverityError, Path: rule.Path.clone(),
|
Message: "overlays cannot contribute to or replace the schema-version path", Primary: &location,
|
||||||
Message: "overlays cannot contribute to or replace the schema-version path", Primary: &location,
|
}}
|
||||||
}}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
base.current.inputBytes += int64(len(data))
|
base.current.inputBytes += int64(len(data))
|
||||||
base.current.inputNodes += nodeCount
|
base.current.inputNodes += nodeCount
|
||||||
|
|||||||
@@ -585,7 +585,21 @@ func TestLoadOverlayCountsAgainstAggregateBudgets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
base.inputBytes = main.bytes
|
base.inputBytes = main.bytes
|
||||||
base.inputNodes = countInputNodes(main.document)
|
base.inputNodes = countInputNodes(main.document)
|
||||||
_, _, diagnostics = loadSelectedOverlayDocument(File(mainPath), nil, main, base, sourceInfos(main.source), "testing", nil, test.limits(main, len(overlayData)))
|
resolved, diagnostic := resolveFilesystemContext(File(mainPath), nil, main, nil)
|
||||||
|
if diagnostic != nil {
|
||||||
|
t.Fatal(diagnostic)
|
||||||
|
}
|
||||||
|
request := selectedOverlayRequest{
|
||||||
|
name: "testing", filesystem: resolved, limits: test.limits(main, len(overlayData)),
|
||||||
|
}
|
||||||
|
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
|
||||||
|
t.Fatal(diagnostic)
|
||||||
|
}
|
||||||
|
access, diagnostic := openSelectedOverlayAccess(resolved)
|
||||||
|
if diagnostic != nil {
|
||||||
|
t.Fatal(diagnostic)
|
||||||
|
}
|
||||||
|
_, diagnostics = loadSelectedOverlay(request, access, newAssemblyAccumulator(base), sourceInfos(main.source))
|
||||||
if len(diagnostics) == 0 || diagnostics[0].Code != CodeOverlayLimitExceeded {
|
if len(diagnostics) == 0 || diagnostics[0].Code != CodeOverlayLimitExceeded {
|
||||||
t.Fatalf("diagnostics = %#v", diagnostics)
|
t.Fatalf("diagnostics = %#v", diagnostics)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,30 +66,6 @@ func contextsForResolvedSources(resolved *resolvedFilesystemContext, sources []S
|
|||||||
return result, nil
|
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) {
|
func mergeResourceContexts(target *map[string]ResourceContext, incoming map[string]ResourceContext) {
|
||||||
if len(incoming) == 0 {
|
if len(incoming) == 0 {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1487,9 +1487,22 @@ func TestSourceVersionOverlayProtectsMountedMainAndPreservesSequenceCoordinates(
|
|||||||
t.Fatalf("compose base: %#v", compositionDiagnostics)
|
t.Fatalf("compose base: %#v", compositionDiagnostics)
|
||||||
}
|
}
|
||||||
assembly := newAssemblyAccumulator(base)
|
assembly := newAssemblyAccumulator(base)
|
||||||
_, diagnostics = loadSelectedOverlayIntoWithVersion(
|
resolved, diagnostic := resolveFilesystemContext(File(mainPath), nil, main, nil)
|
||||||
File(mainPath), nil, main, assembly, sourceInfos(main.source), "testing", effectiveRule, defaultImportLimits(), state,
|
if diagnostic != nil {
|
||||||
)
|
t.Fatalf("resolve overlay context: %#v", diagnostic)
|
||||||
|
}
|
||||||
|
request := selectedOverlayRequest{
|
||||||
|
name: "testing", filesystem: resolved, protectionRule: effectiveRule,
|
||||||
|
limits: defaultImportLimits(), versionState: state,
|
||||||
|
}
|
||||||
|
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
|
||||||
|
t.Fatalf("validate overlay context: %#v", diagnostic)
|
||||||
|
}
|
||||||
|
access, diagnostic := openSelectedOverlayAccess(resolved)
|
||||||
|
if diagnostic != nil {
|
||||||
|
t.Fatalf("open overlay context: %#v", diagnostic)
|
||||||
|
}
|
||||||
|
_, diagnostics = loadSelectedOverlay(request, access, assembly, sourceInfos(main.source))
|
||||||
if len(diagnostics) != 0 {
|
if len(diagnostics) != 0 {
|
||||||
t.Fatalf("load selected overlay: %#v", diagnostics)
|
t.Fatalf("load selected overlay: %#v", diagnostics)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user