in sg/internal/source/fs.go [64:163]
func loadSourceFromPaths(contextRoot string, paths []string) ([]Source, error) {
// when contextRoot specified, all paths must be relative to contextRoot.
// FIXME(hbc): this implementation may not be correct in Windows (see context in `filepath.HasPrefix`)
// We should revisit this in later changes.
if contextRoot != "" {
contextRootAbs, err := filepath.Abs(contextRoot)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path of context root %q: %w", contextRoot, err)
}
for _, p := range paths {
pAbs, err := filepath.Abs(p)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path of %q: %w", p, err)
}
if !strings.HasPrefix(pAbs, contextRootAbs) {
return nil, fmt.Errorf("path %q is not relative to context root %q", p, contextRoot)
}
}
}
relativeToContextRoot := relativeToContextRootFn(contextRoot)
var files []string
var jsonFiles []string
walk := func(path string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if parser.FileSupported(path) {
if strings.EqualFold(filepath.Ext(path)[1:], parser.JSON) {
jsonFiles = append(jsonFiles, path)
} else {
files = append(files, path)
}
}
return nil
}
for _, path := range paths {
if err := filepath.WalkDir(path, walk); err != nil {
return nil, fmt.Errorf("walk path %q: %w", path, err)
}
}
if len(files)+len(jsonFiles) < 1 {
return nil, fmt.Errorf("no files found from given paths: %v", paths)
}
// parse json files with jsonc to allow comments
jsonConfigurations, err := parser.ParseConfigurationsAs(jsonFiles, parser.JSONC)
if err != nil {
return nil, fmt.Errorf("parse configurations: %w", err)
}
configurations, err := parser.ParseConfigurations(files)
if err != nil {
return nil, fmt.Errorf("parse configurations: %w", err)
}
maps.Copy(configurations, jsonConfigurations)
filePathsSorted := make([]string, 0, len(configurations))
for filePath := range configurations {
filePathsSorted = append(filePathsSorted, filePath)
}
sort.Strings(filePathsSorted)
var rv []Source
for _, filePath := range filePathsSorted {
c := configurations[filePath]
var subConfigurations []any
if cc, ok := c.([]any); ok {
subConfigurations = cc
} else {
subConfigurations = []any{c}
}
var parsedConfigurations []ast.Value
for _, rawConfiguration := range subConfigurations {
parsedConfiguration, err := parseRawConfiguration(rawConfiguration)
if err != nil {
return nil, fmt.Errorf("parse raw configuration: %w", err)
}
parsedConfigurations = append(parsedConfigurations, parsedConfiguration)
}
rv = append(rv, &fsSource{
filePath: relativeToContextRoot(filePath),
configurations: parsedConfigurations,
})
}
return rv, nil
}