Unify host and native filesystem acquisition
This commit is contained in:
@@ -4,10 +4,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
yamladapter "gitea.maximumdirect.net/eric/ConfigKit/internal/yaml"
|
||||
)
|
||||
@@ -41,12 +38,32 @@ func loadSelectedOverlayDocument(source Source, context *FilesystemContext, main
|
||||
}
|
||||
|
||||
func loadSelectedOverlayInto(source Source, context *FilesystemContext, main parsedSource, base *assemblyAccumulator, sources []SourceInfo, name string, rule *VersionRule, limits importLimits) ([]SourceInfo, []Diagnostic) {
|
||||
if source.kind == sourceFilesystem {
|
||||
access := newNativeAccess(source.namespace.filesystem, ".", source.namespace.token)
|
||||
return loadSelectedOverlayWithAccess(access, base, sources, name, rule, limits)
|
||||
}
|
||||
rootPath, _, _, diagnostic := importFilesystem(source, context, main)
|
||||
if diagnostic != nil {
|
||||
return cloneSourceInfos(sources), []Diagnostic{*diagnostic}
|
||||
}
|
||||
overlayPath := filepath.Join(rootPath, "overlays", name+".yml")
|
||||
canonical, err := canonicalExistingPath(overlayPath)
|
||||
access, err := openHostAccess(rootPath)
|
||||
if err != nil {
|
||||
value := globFilesystemDiagnostic(err, "configuration root could not be opened for the selected overlay", Location{})
|
||||
value.Primary = nil
|
||||
return cloneSourceInfos(sources), []Diagnostic{value}
|
||||
}
|
||||
return loadSelectedOverlayWithAccess(access, base, sources, name, rule, limits)
|
||||
}
|
||||
|
||||
func loadSelectedOverlayWithAccess(access *filesystemAccess, base *assemblyAccumulator, sources []SourceInfo, name string, rule *VersionRule, limits importLimits) ([]SourceInfo, []Diagnostic) {
|
||||
closed := false
|
||||
defer func() {
|
||||
if !closed {
|
||||
_ = access.close()
|
||||
}
|
||||
}()
|
||||
overlayPath := access.join(access.rootPath, "overlays/"+name+".yml")
|
||||
canonical, err := access.canonical(overlayPath)
|
||||
if err != nil {
|
||||
code := CodeOverlayInvalid
|
||||
message := "selected overlay could not be resolved"
|
||||
@@ -57,7 +74,7 @@ func loadSelectedOverlayInto(source Source, context *FilesystemContext, main par
|
||||
}
|
||||
return cloneSourceInfos(sources), []Diagnostic{importDiagnostic(code, message, nil)}
|
||||
}
|
||||
if !containedPath(rootPath, canonical) {
|
||||
if !access.contains(canonical) {
|
||||
return cloneSourceInfos(sources), []Diagnostic{importDiagnostic(CodeOverlayOutsideRoot, "selected overlay resolves outside the configuration root", nil)}
|
||||
}
|
||||
for _, existing := range sources {
|
||||
@@ -69,28 +86,15 @@ func loadSelectedOverlayInto(source Source, context *FilesystemContext, main par
|
||||
return cloneSourceInfos(sources), []Diagnostic{importDiagnostic(CodeOverlayLimitExceeded, "selected overlay exceeds the source-count limit", nil)}
|
||||
}
|
||||
|
||||
root, err := os.OpenRoot(rootPath)
|
||||
if err != nil {
|
||||
value := globFilesystemDiagnostic(err, "configuration root could not be opened for the selected overlay", Location{})
|
||||
value.Primary = nil
|
||||
return cloneSourceInfos(sources), []Diagnostic{value}
|
||||
}
|
||||
rootClosed := false
|
||||
defer func() {
|
||||
if !rootClosed {
|
||||
_ = root.Close()
|
||||
}
|
||||
}()
|
||||
relative, err := filepath.Rel(rootPath, canonical)
|
||||
if err != nil || filepath.IsAbs(relative) || relative == ".." || strings.HasPrefix(relative, ".."+string(filepath.Separator)) {
|
||||
if _, err := access.relative(canonical); err != nil {
|
||||
return cloneSourceInfos(sources), []Diagnostic{importDiagnostic(CodeOverlayOutsideRoot, "selected overlay could not be addressed inside the configuration root", nil)}
|
||||
}
|
||||
|
||||
sourceID := "source-" + strconv.Itoa(len(sources)+1)
|
||||
overlayLocation := &Location{SourceID: sourceID}
|
||||
overlaySource := SourceInfo{ID: sourceID, Label: filepath.ToSlash(filepath.Join("overlays", name+".yml")), Path: canonical, Layer: LayerOverlay}
|
||||
overlaySource := SourceInfo{ID: sourceID, Label: "overlays/" + name + ".yml", Path: canonical, Layer: LayerOverlay}
|
||||
sources = append(cloneSourceInfos(sources), overlaySource)
|
||||
data, diagnostic := readOverlayFile(root, relative, sourceID, limits.bytes-base.current.inputBytes)
|
||||
data, diagnostic := readOverlayFile(access, canonical, sourceID, limits.bytes-base.current.inputBytes)
|
||||
if diagnostic != nil {
|
||||
return sources, []Diagnostic{*diagnostic}
|
||||
}
|
||||
@@ -112,8 +116,8 @@ func loadSelectedOverlayInto(source Source, context *FilesystemContext, main par
|
||||
Message: "overlays cannot contribute to or replace the schema-version path", Primary: &location,
|
||||
}}
|
||||
}
|
||||
closeErr := root.Close()
|
||||
rootClosed = true
|
||||
closeErr := access.close()
|
||||
closed = true
|
||||
if closeErr != nil {
|
||||
return sources, []Diagnostic{importDiagnostic(CodeImportRead, "configuration root could not be closed after reading the selected overlay", nil)}
|
||||
}
|
||||
@@ -126,12 +130,12 @@ func loadSelectedOverlayInto(source Source, context *FilesystemContext, main par
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
func readOverlayFile(root *os.Root, relative, sourceID string, remaining int64) ([]byte, *Diagnostic) {
|
||||
func readOverlayFile(access *filesystemAccess, name, sourceID string, remaining int64) ([]byte, *Diagnostic) {
|
||||
limit := min(int64(maxSourceBytes), remaining)
|
||||
if limit < 0 {
|
||||
limit = 0
|
||||
}
|
||||
data, failure := readRegularFile(relative, root.Stat, root.Open, limit)
|
||||
data, failure := readRegularFile(name, access.stat, access.open, limit)
|
||||
if failure != nil {
|
||||
value := sourceReadDiagnostic(failure, sourceID, CodeOverlayLimitExceeded, "selected overlay exceeds a source or aggregate byte limit")
|
||||
return nil, &value
|
||||
|
||||
Reference in New Issue
Block a user