Separate filesystem context from access
This commit is contained in:
@@ -3,7 +3,6 @@ package engine
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
@@ -137,32 +136,17 @@ func nativeContext(source Source, context *FilesystemContext) bool {
|
||||
// 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) {
|
||||
var namespace *nativeNamespace
|
||||
rootPath := "."
|
||||
basePath := "."
|
||||
mainPath := ""
|
||||
if source.kind == sourceFilesystem {
|
||||
namespace = source.namespace
|
||||
mainPath = source.path
|
||||
basePath = path.Dir(source.path)
|
||||
if context != nil && context.Root != "" {
|
||||
rootPath = context.Root
|
||||
}
|
||||
} else if context != nil && context.FS != nil {
|
||||
namespace = context.FS.namespace
|
||||
rootPath, basePath = context.Root, context.BaseDir
|
||||
resolved, diagnostic := resolveNativeFilesystemContext(source, context)
|
||||
if diagnostic != nil {
|
||||
return nil, "", "", diagnostic
|
||||
}
|
||||
if namespace == nil || nilFilesystem(namespace.filesystem) || !fs.ValidPath(rootPath) || !fs.ValidPath(basePath) {
|
||||
value := optionDiagnostic(CodeOptionsInvalid, "filesystem context is invalid")
|
||||
access, err := openResolvedFilesystemAccess(resolved)
|
||||
if err != nil {
|
||||
value := globFilesystemDiagnostic(err, "configuration root could not be opened", Location{})
|
||||
value.Primary = nil
|
||||
return nil, "", "", &value
|
||||
}
|
||||
access := newNativeAccess(namespace.filesystem, rootPath, namespace.token)
|
||||
access.label = namespace.label
|
||||
if !access.contains(basePath) || mainPath != "" && !access.contains(mainPath) {
|
||||
value := importDiagnostic(CodeImportOutsideRoot, "selected source and import base must stay inside the configuration root", nil)
|
||||
return nil, "", "", &value
|
||||
}
|
||||
return access, basePath, mainPath, nil
|
||||
return access, resolved.basePath, resolved.mainPath, nil
|
||||
}
|
||||
|
||||
func validateNativeDirectories(access *filesystemAccess, basePath, mainPath string) *Diagnostic {
|
||||
@@ -181,64 +165,14 @@ func validateNativeDirectories(access *filesystemAccess, basePath, mainPath stri
|
||||
}
|
||||
|
||||
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 source.kind == sourceFile {
|
||||
if context != nil && context.BaseDir != "" {
|
||||
value := optionDiagnostic(CodeOptionsInvalid, "file sources determine their own import base directory")
|
||||
return "", "", "", &value
|
||||
}
|
||||
canonical, err := canonicalExistingPath(source.path)
|
||||
if err != nil {
|
||||
value := importDiagnostic(CodeImportInvalid, "selected source path could not be canonicalized", nil)
|
||||
return "", "", "", &value
|
||||
}
|
||||
mainPath = canonical
|
||||
basePath = filepath.Dir(canonical)
|
||||
rootPath = basePath
|
||||
if context != nil && context.Root != "" {
|
||||
rootPath, err = canonicalExistingPath(context.Root)
|
||||
if err != nil {
|
||||
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
|
||||
return "", "", "", &value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if context == nil || context.BaseDir == "" || context.Root == "" {
|
||||
value := optionDiagnostic(CodeOptionsInvalid, "byte and reader imports require absolute base and root directories")
|
||||
return "", "", "", &value
|
||||
}
|
||||
if !filepath.IsAbs(context.BaseDir) || !filepath.IsAbs(context.Root) {
|
||||
value := optionDiagnostic(CodeOptionsInvalid, "byte and reader import base and root directories must be absolute")
|
||||
return "", "", "", &value
|
||||
}
|
||||
var err error
|
||||
basePath, err = canonicalExistingPath(context.BaseDir)
|
||||
if err != nil {
|
||||
value := importDiagnostic(CodeImportInvalid, "import base directory could not be canonicalized", nil)
|
||||
return "", "", "", &value
|
||||
}
|
||||
rootPath, err = canonicalExistingPath(context.Root)
|
||||
if err != nil {
|
||||
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
|
||||
return "", "", "", &value
|
||||
}
|
||||
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
|
||||
return "", "", "", diagnostic
|
||||
}
|
||||
if !containedPath(rootPath, basePath) || (mainPath != "" && !containedPath(rootPath, mainPath)) {
|
||||
value := importDiagnostic(CodeImportOutsideRoot, "selected source and import base must stay inside the configuration root", nil)
|
||||
return "", "", "", &value
|
||||
}
|
||||
for _, candidate := range []string{rootPath, basePath} {
|
||||
info, err := os.Stat(candidate)
|
||||
if err != nil || !info.IsDir() {
|
||||
value := importDiagnostic(CodeImportInvalid, "configuration root and import base must be directories", nil)
|
||||
return "", "", "", &value
|
||||
}
|
||||
}
|
||||
return rootPath, basePath, mainPath, nil
|
||||
return resolved.rootPath, resolved.basePath, resolved.mainPath, nil
|
||||
}
|
||||
|
||||
func canonicalExistingPath(name string) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user