Implement a "from" to config files that loads other files
This commit is contained in:
@@ -20,6 +20,7 @@ type LinkInstruction struct {
|
||||
|
||||
type YAMLConfig struct {
|
||||
Links []LinkInstruction `yaml:"links"`
|
||||
From []string `yaml:"from,omitempty"`
|
||||
}
|
||||
|
||||
func (instruction *LinkInstruction) Tidy() {
|
||||
@@ -318,9 +319,76 @@ func ParseYAMLFile(filename, workdir string) ([]LinkInstruction, error) {
|
||||
return expanded, nil
|
||||
}
|
||||
|
||||
// ParseYAMLFileRecursive parses a YAML file and recursively processes any "From" references
|
||||
func ParseYAMLFileRecursive(filename, workdir string) ([]LinkInstruction, error) {
|
||||
visited := make(map[string]bool)
|
||||
return parseYAMLFileRecursive(filename, workdir, visited)
|
||||
}
|
||||
|
||||
// parseYAMLFileRecursive is the internal recursive function that tracks visited files to prevent cycles
|
||||
func parseYAMLFileRecursive(filename, workdir string, visited map[string]bool) ([]LinkInstruction, error) {
|
||||
// Normalize the filename to prevent cycles with different path representations
|
||||
normalizedFilename, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error normalizing filename: %w", err)
|
||||
}
|
||||
|
||||
// Check for cycles
|
||||
if visited[normalizedFilename] {
|
||||
return nil, fmt.Errorf("circular reference detected: %s", filename)
|
||||
}
|
||||
visited[normalizedFilename] = true
|
||||
defer delete(visited, normalizedFilename)
|
||||
|
||||
// Parse the current file
|
||||
instructions, err := ParseYAMLFile(filename, workdir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Read the file to check for "From" references
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading YAML file: %w", err)
|
||||
}
|
||||
|
||||
var config YAMLConfig
|
||||
err = yaml.Unmarshal(data, &config)
|
||||
if err != nil {
|
||||
// If parsing as YAMLConfig fails, there are no "From" references to process
|
||||
return instructions, nil
|
||||
}
|
||||
|
||||
// Process "From" references
|
||||
for _, fromFile := range config.From {
|
||||
// Convert relative paths to absolute paths based on the current file's directory
|
||||
fromPath := fromFile
|
||||
if !filepath.IsAbs(fromPath) {
|
||||
currentDir := filepath.Dir(filename)
|
||||
fromPath = filepath.Join(currentDir, fromPath)
|
||||
}
|
||||
|
||||
// Normalize the path
|
||||
fromPath = filepath.Clean(fromPath)
|
||||
|
||||
// Recursively parse the referenced file
|
||||
// Use the directory of the referenced file as the workdir for pattern expansion
|
||||
fromWorkdir := filepath.Dir(fromPath)
|
||||
fromInstructions, err := parseYAMLFileRecursive(fromPath, fromWorkdir, visited)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing referenced file %s: %w", fromFile, err)
|
||||
}
|
||||
|
||||
// Append the instructions from the referenced file
|
||||
instructions = append(instructions, fromInstructions...)
|
||||
}
|
||||
|
||||
return instructions, nil
|
||||
}
|
||||
|
||||
func ExpandPattern(source, workdir, target string) (links []LinkInstruction, err error) {
|
||||
static, pattern := doublestar.SplitPattern(source)
|
||||
if static == "" {
|
||||
if static == "" || static == "." {
|
||||
static = workdir
|
||||
}
|
||||
LogInfo("Static part: %s", static)
|
||||
|
Reference in New Issue
Block a user