168 lines
6.6 KiB
Go
168 lines
6.6 KiB
Go
package config
|
|
|
|
import (
|
|
"path/filepath"
|
|
|
|
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
|
)
|
|
|
|
func normalizeDocumentPaths(document *Document, context *configkit.Resolution, state *documentLoadState) {
|
|
resolution := documentNormalizer{Resolution: context}
|
|
if document == nil {
|
|
return
|
|
}
|
|
initializeDocumentMainDirectory(resolution, state)
|
|
if document.PromptKit != nil {
|
|
normalizeDocumentPath(resolution, state, configkit.Keys("promptkit", "profile_dir"), &document.PromptKit.ProfileDir, false, "resolved PromptKit profile directory")
|
|
normalizeDocumentPath(resolution, state, configkit.Keys("promptkit", "profile_file"), &document.PromptKit.ProfileFile, false, "resolved PromptKit profile file")
|
|
}
|
|
if document.Output != nil {
|
|
normalizeDocumentPath(resolution, state, configkit.Keys("output", "directory"), &document.Output.Directory, false, "resolved output directory")
|
|
}
|
|
if document.Cache != nil {
|
|
if document.Cache.ChunkPlans != nil {
|
|
normalizeDocumentPath(resolution, state, configkit.Keys("cache", "chunk_plans", "directory"), &document.Cache.ChunkPlans.Directory, true, "resolved chunk-plan cache directory")
|
|
}
|
|
if document.Cache.Checkpoints != nil {
|
|
normalizeDocumentPath(resolution, state, configkit.Keys("cache", "checkpoints", "directory"), &document.Cache.Checkpoints.Directory, true, "resolved checkpoint cache directory")
|
|
}
|
|
}
|
|
if document.Debug != nil {
|
|
normalizeDocumentPath(resolution, state, configkit.Keys("debug", "directory"), &document.Debug.Directory, false, "resolved debug directory")
|
|
}
|
|
for _, id := range sortedPipelineDocumentKeys(document.Pipelines) {
|
|
profile := document.Pipelines[id]
|
|
path := configkit.Keys("pipelines").Key(id)
|
|
normalizeDocumentReferencePaths(profile.References, path.Key("references"), resolution, state)
|
|
normalizeDocumentBindingReferencePaths(&profile.Input, path.Key("input"), resolution, state)
|
|
if profile.Chunk != nil {
|
|
normalizeDocumentBindingReferencePaths(profile.Chunk, path.Key("chunk"), resolution, state)
|
|
}
|
|
if profile.Output != nil {
|
|
normalizeDocumentBindingReferencePaths(profile.Output, path.Key("output"), resolution, state)
|
|
}
|
|
for laneID, lane := range profile.Artifacts {
|
|
normalizeDocumentLaneReferencePaths(&lane, path.Key("artifacts").Key(laneID), resolution, state)
|
|
profile.Artifacts[laneID] = lane
|
|
}
|
|
stepResolution := resolution.inSequence(path.Key("steps"))
|
|
for index := range profile.Steps {
|
|
step := &profile.Steps[index]
|
|
stepPath := path.Key("steps").Index(index)
|
|
normalizeDocumentReferencePaths(step.References, stepPath.Key("references"), stepResolution, state)
|
|
for laneID, lane := range step.Artifacts {
|
|
normalizeDocumentLaneReferencePaths(&lane, stepPath.Key("artifacts").Key(laneID), stepResolution, state)
|
|
step.Artifacts[laneID] = lane
|
|
}
|
|
}
|
|
document.Pipelines[id] = profile
|
|
}
|
|
}
|
|
|
|
func initializeDocumentMainDirectory(resolution documentNormalizer, state *documentLoadState) {
|
|
if state == nil || state.mainDirectory != "" {
|
|
return
|
|
}
|
|
info, ok := resolution.InputInfo(configkit.Keys("version"))
|
|
if ok && len(info.Origin.Locations) == 1 {
|
|
if source, sourceOK := resolution.Source(info.Origin.Locations[0].SourceID); sourceOK && source.Path != "" {
|
|
state.mainDirectory = filepath.Dir(source.Path)
|
|
return
|
|
}
|
|
}
|
|
// Byte and reader sources are test-oriented private entry points. They have
|
|
// no declaring file, so preserve their established invocation-directory
|
|
// semantics without extending that fallback to file-backed production loads.
|
|
state.mainDirectory = cleanInvocationDirectory(".")
|
|
}
|
|
|
|
func normalizeDocumentBindingReferencePaths(binding *BindingDocument, path configkit.Path, resolution documentNormalizer, state *documentLoadState) {
|
|
if binding != nil {
|
|
normalizeDocumentReferencePaths(binding.References, path.Key("references"), resolution, state)
|
|
}
|
|
}
|
|
|
|
func normalizeDocumentLaneReferencePaths(lane *ArtifactLaneDocument, path configkit.Path, resolution documentNormalizer, state *documentLoadState) {
|
|
if lane == nil {
|
|
return
|
|
}
|
|
normalizeDocumentBindingReferencePaths(&lane.Extract, path.Key("extract"), resolution, state)
|
|
normalizeDocumentBindingReferencePaths(lane.Merge, path.Key("merge"), resolution, state)
|
|
normalizeDocumentBindingReferencePaths(lane.Normalize, path.Key("normalize"), resolution, state)
|
|
}
|
|
|
|
func normalizeDocumentReferencePaths(references map[string]ReferenceDocument, path configkit.Path, resolution documentNormalizer, state *documentLoadState) {
|
|
for _, name := range sortedReferenceDocumentKeys(references) {
|
|
source := references[name]
|
|
sourcePath := path.Key(name).Key("path")
|
|
if source.Path != nil && *source.Path != "" && !filepath.IsAbs(*source.Path) {
|
|
base, ok := documentPathBase(resolution, state, sourcePath)
|
|
if !ok {
|
|
resolution.Error(sourcePath, "relative path has no unambiguous source base")
|
|
} else {
|
|
value := filepath.Clean(filepath.Join(base, *source.Path))
|
|
if value != *source.Path {
|
|
resolution.Record(sourcePath, configkit.ChangeNormalization, "resolved external reference path")
|
|
source.Path = documentValue(value)
|
|
}
|
|
}
|
|
references[name] = source
|
|
}
|
|
}
|
|
}
|
|
|
|
func normalizeDocumentPath(resolution documentNormalizer, state *documentLoadState, path configkit.Path, target **string, optional bool, reason string) {
|
|
if target == nil || *target == nil || **target == "" || filepath.IsAbs(**target) {
|
|
return
|
|
}
|
|
base, ok := documentPathBase(resolution, state, path)
|
|
if !ok {
|
|
resolution.Error(path, "relative path has no unambiguous source base")
|
|
return
|
|
}
|
|
value := filepath.Clean(filepath.Join(base, **target))
|
|
if optional && **target == "" {
|
|
return
|
|
}
|
|
if *target != nil && **target != value {
|
|
configkit.Normalize(resolution.Resolution, path, target, documentValue(value), reason)
|
|
}
|
|
}
|
|
|
|
func documentPathBase(resolution documentNormalizer, state *documentLoadState, path configkit.Path) (string, bool) {
|
|
original := path
|
|
if state != nil {
|
|
original = state.originalPath(path)
|
|
}
|
|
info, ok := resolution.InputInfo(original)
|
|
if !ok {
|
|
if state != nil && state.mainDirectory != "" {
|
|
return state.mainDirectory, true
|
|
}
|
|
return "", false
|
|
}
|
|
switch info.Origin.Layer {
|
|
case configkit.LayerCLI:
|
|
if state != nil && state.invocationDirectory != "" {
|
|
return state.invocationDirectory, true
|
|
}
|
|
case configkit.LayerDefault:
|
|
if state != nil && state.mainDirectory != "" {
|
|
return state.mainDirectory, true
|
|
}
|
|
default:
|
|
if len(info.Origin.Locations) != 1 {
|
|
return "", false
|
|
}
|
|
source, ok := resolution.Source(info.Origin.Locations[0].SourceID)
|
|
if !ok || source.Path == "" {
|
|
if state != nil && state.mainDirectory != "" {
|
|
return state.mainDirectory, true
|
|
}
|
|
return "", false
|
|
}
|
|
return filepath.Dir(source.Path), true
|
|
}
|
|
return "", false
|
|
}
|