mirror of
https://github.com/mikefarah/yq.git
synced 2026-03-30 23:10:06 +00:00
When using --front-matter, yq creates a temporary file for the extracted YAML content but replaces the original filename in args with the temp file path. This caused the 'filename' operator to return the temp file path instead of the original filename. Added a filename alias mechanism: when front matter processing replaces the file path, it registers the original filename as an alias. The readDocuments and stream evaluator functions resolve aliases before setting candidateNode.filename. Fixes #2538 Co-authored-by: cobyfrombrooklyn-bot <cobyfrombrooklyn@gmail.com>
162 lines
4.0 KiB
Go
162 lines
4.0 KiB
Go
package cmd
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func createEvaluateSequenceCommand() *cobra.Command {
|
|
var cmdEvalSequence = &cobra.Command{
|
|
Use: "eval [expression] [yaml_file1]...",
|
|
Aliases: []string{"e"},
|
|
Short: "(default) Apply the expression to each document in each yaml file in sequence",
|
|
ValidArgsFunction: func(_ *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) {
|
|
if len(args) == 0 {
|
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
return nil, cobra.ShellCompDirectiveDefault
|
|
},
|
|
Example: `
|
|
# Reads field under the given path for each file
|
|
yq e '.a.b' f1.yml f2.yml
|
|
|
|
# Prints out the file
|
|
yq e sample.yaml
|
|
|
|
# Pipe from STDIN
|
|
## use '-' as a filename to pipe from STDIN
|
|
cat file2.yml | yq e '.a.b' file1.yml - file3.yml
|
|
|
|
# Creates a new yaml document
|
|
## Note that editing an empty file does not work.
|
|
yq e -n '.a.b.c = "cat"'
|
|
|
|
# Update a file in place
|
|
yq e '.a.b = "cool"' -i file.yaml
|
|
`,
|
|
Long: `yq is a portable command-line data file processor (https://github.com/mikefarah/yq/)
|
|
See https://mikefarah.gitbook.io/yq/ for detailed documentation and examples.
|
|
|
|
## Evaluate Sequence ##
|
|
This command iterates over each yaml document from each given file, applies the
|
|
expression and prints the result in sequence.`,
|
|
RunE: evaluateSequence,
|
|
}
|
|
return cmdEvalSequence
|
|
}
|
|
|
|
func processExpression(expression string) string {
|
|
|
|
if prettyPrint && expression == "" {
|
|
return yqlib.PrettyPrintExp
|
|
} else if prettyPrint {
|
|
return fmt.Sprintf("%v | %v", expression, yqlib.PrettyPrintExp)
|
|
}
|
|
return expression
|
|
}
|
|
|
|
func evaluateSequence(cmd *cobra.Command, args []string) (cmdError error) {
|
|
// 0 args, read std in
|
|
// 1 arg, null input, process expression
|
|
// 1 arg, read file in sequence
|
|
// 2+ args, [0] = expression, file the rest
|
|
|
|
out := cmd.OutOrStdout()
|
|
|
|
var err error
|
|
|
|
expression, args, err := initCommand(cmd, args)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if writeInplace {
|
|
// only use colours if its forced
|
|
colorsEnabled = forceColor
|
|
writeInPlaceHandler := yqlib.NewWriteInPlaceHandler(args[0])
|
|
out, err = writeInPlaceHandler.CreateTempFile()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// need to indirectly call the function so that completedSuccessfully is
|
|
// passed when we finish execution as opposed to now
|
|
defer func() {
|
|
if cmdError == nil {
|
|
cmdError = writeInPlaceHandler.FinishWriteInPlace(completedSuccessfully)
|
|
}
|
|
}()
|
|
}
|
|
|
|
format, err := yqlib.FormatFromString(outputFormat)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
printerWriter, err := configurePrinterWriter(format, out)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
encoder, err := configureEncoder()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
printer := yqlib.NewPrinter(encoder, printerWriter)
|
|
|
|
if printNodeInfo {
|
|
printer = yqlib.NewNodeInfoPrinter(printerWriter)
|
|
}
|
|
|
|
if nulSepOutput {
|
|
printer.SetNulSepOutput(true)
|
|
}
|
|
|
|
decoder, err := configureDecoder(false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
streamEvaluator := yqlib.NewStreamEvaluator()
|
|
|
|
if frontMatter != "" {
|
|
yqlib.GetLogger().Debug("using front matter handler")
|
|
originalFilename := args[0]
|
|
frontMatterHandler := yqlib.NewFrontMatterHandler(args[0])
|
|
err = frontMatterHandler.Split()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
args[0] = frontMatterHandler.GetYamlFrontMatterFilename()
|
|
yqlib.SetFilenameAlias(args[0], originalFilename)
|
|
defer yqlib.ClearFilenameAliases()
|
|
|
|
if frontMatter == "process" {
|
|
reader := frontMatterHandler.GetContentReader()
|
|
printer.SetAppendix(reader)
|
|
defer yqlib.SafelyCloseReader(reader)
|
|
}
|
|
defer frontMatterHandler.CleanUp()
|
|
}
|
|
|
|
switch len(args) {
|
|
case 0:
|
|
if nullInput {
|
|
err = streamEvaluator.EvaluateNew(processExpression(expression), printer)
|
|
} else {
|
|
cmd.Println(cmd.UsageString())
|
|
return nil
|
|
}
|
|
default:
|
|
err = streamEvaluator.EvaluateFiles(processExpression(expression), args, printer, decoder)
|
|
}
|
|
completedSuccessfully = err == nil
|
|
|
|
if err == nil && exitStatus && !printer.PrintedAnything() {
|
|
return errors.New("no matches found")
|
|
}
|
|
|
|
return err
|
|
}
|