yq/cmd/evaluate_all_command.go

158 lines
5.1 KiB
Go
Raw Normal View History

2020-11-13 02:19:54 +00:00
package cmd
import (
2020-11-30 05:35:21 +00:00
"errors"
2020-11-13 02:19:54 +00:00
"os"
"github.com/mikefarah/yq/v4/pkg/yqlib"
"github.com/spf13/cobra"
)
func createEvaluateAllCommand() *cobra.Command {
var cmdEvalAll = &cobra.Command{
Use: "eval-all [expression] [yaml_file1]...",
Aliases: []string{"ea"},
2020-11-13 03:07:11 +00:00
Short: "Loads _all_ yaml documents of _all_ yaml files and runs expression once",
2020-11-13 02:19:54 +00:00
Example: `
# Merge f2.yml into f1.yml (inplace)
yq eval-all --inplace 'select(fileIndex == 0) * select(fileIndex == 1)' f1.yml f2.yml
## the same command and expression using shortened names:
yq ea -i 'select(fi == 0) * select(fi == 1)' f1.yml f2.yml
2021-04-19 00:26:58 +00:00
# Merge all given files
yq ea '. as $item ireduce ({}; . * $item )' file1.yml file2.yml ...
2021-09-19 23:57:41 +00:00
# Pipe from STDIN
## use '-' as a filename to pipe from STDIN
2021-04-19 00:26:58 +00:00
cat file2.yml | yq ea '.a.b' file1.yml - file3.yml
2020-11-13 02:19:54 +00:00
`,
Long: `yq is a portable command-line YAML processor (https://github.com/mikefarah/yq/)
See https://mikefarah.gitbook.io/yq/ for detailed documentation and examples.
## Evaluate All ##
This command loads _all_ yaml documents of _all_ yaml files and runs expression once
Useful when you need to run an expression across several yaml documents or files (like merge).
Note that it consumes more memory than eval.
`,
2020-11-13 02:19:54 +00:00
RunE: evaluateAll,
}
return cmdEvalAll
}
func evaluateAll(cmd *cobra.Command, args []string) (cmdError error) {
2020-11-13 02:19:54 +00:00
// 0 args, read std in
// 1 arg, null input, process expression
// 1 arg, read file in sequence
// 2+ args, [0] = expression, file the rest
var err error
2021-10-30 02:04:05 +00:00
firstFileIndex, err := initCommand(cmd, args)
if err != nil {
return err
2021-02-10 06:06:16 +00:00
}
2021-10-30 02:04:05 +00:00
stat, _ := os.Stdin.Stat()
pipingStdIn := (stat.Mode() & os.ModeCharDevice) == 0
2022-01-27 02:24:05 +00:00
yqlib.GetLogger().Debug("pipingStdIn: %v", pipingStdIn)
2020-11-29 09:25:47 +00:00
2022-01-27 02:54:29 +00:00
yqlib.GetLogger().Debug("stat.Mode(): %v", stat.Mode())
yqlib.GetLogger().Debug("ModeDir: %v", stat.Mode()&os.ModeDir)
yqlib.GetLogger().Debug("ModeAppend: %v", stat.Mode()&os.ModeAppend)
yqlib.GetLogger().Debug("ModeExclusive: %v", stat.Mode()&os.ModeExclusive)
yqlib.GetLogger().Debug("ModeTemporary: %v", stat.Mode()&os.ModeTemporary)
yqlib.GetLogger().Debug("ModeSymlink: %v", stat.Mode()&os.ModeSymlink)
yqlib.GetLogger().Debug("ModeDevice: %v", stat.Mode()&os.ModeDevice)
yqlib.GetLogger().Debug("ModeNamedPipe: %v", stat.Mode()&os.ModeNamedPipe)
yqlib.GetLogger().Debug("ModeSocket: %v", stat.Mode()&os.ModeSocket)
yqlib.GetLogger().Debug("ModeSetuid: %v", stat.Mode()&os.ModeSetuid)
yqlib.GetLogger().Debug("ModeSetgid: %v", stat.Mode()&os.ModeSetgid)
yqlib.GetLogger().Debug("ModeCharDevice: %v", stat.Mode()&os.ModeCharDevice)
yqlib.GetLogger().Debug("ModeSticky: %v", stat.Mode()&os.ModeSticky)
yqlib.GetLogger().Debug("ModeIrregular: %v", stat.Mode()&os.ModeIrregular)
2021-10-30 02:04:05 +00:00
out := cmd.OutOrStdout()
2021-10-29 03:14:39 +00:00
2020-11-29 09:25:47 +00:00
if writeInplace {
2020-11-30 05:05:07 +00:00
// only use colors if its forced
colorsEnabled = forceColor
2021-02-10 06:06:16 +00:00
writeInPlaceHandler := yqlib.NewWriteInPlaceHandler(args[firstFileIndex])
2020-11-29 09:25:47 +00:00
out, err = writeInPlaceHandler.CreateTempFile()
if err != nil {
return err
}
2020-11-30 05:05:07 +00:00
// 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)
}
}()
2020-11-29 09:25:47 +00:00
}
2021-07-25 08:08:33 +00:00
format, err := yqlib.OutputFormatFromString(outputFormat)
if err != nil {
return err
}
2021-12-21 04:02:07 +00:00
decoder, err := configureDecoder()
if err != nil {
return err
}
printerWriter, err := configurePrinterWriter(format, out)
if err != nil {
return err
}
encoder := configureEncoder(format)
2021-10-29 03:14:39 +00:00
printer := yqlib.NewPrinter(encoder, printerWriter)
2020-11-29 09:25:47 +00:00
if frontMatter != "" {
frontMatterHandler := yqlib.NewFrontMatterHandler(args[firstFileIndex])
err = frontMatterHandler.Split()
if err != nil {
return err
}
args[firstFileIndex] = frontMatterHandler.GetYamlFrontMatterFilename()
if frontMatter == "process" {
2021-07-20 00:38:42 +00:00
reader := frontMatterHandler.GetContentReader()
printer.SetAppendix(reader)
defer yqlib.SafelyCloseReader(reader)
}
defer frontMatterHandler.CleanUp()
}
2020-11-22 00:56:28 +00:00
allAtOnceEvaluator := yqlib.NewAllAtOnceEvaluator()
2020-11-13 02:19:54 +00:00
switch len(args) {
case 0:
if pipingStdIn {
2021-12-21 04:02:07 +00:00
err = allAtOnceEvaluator.EvaluateFiles(processExpression(""), []string{"-"}, printer, leadingContentPreProcessing, decoder)
2020-11-13 02:19:54 +00:00
} else {
cmd.Println(cmd.UsageString())
return nil
}
case 1:
if nullInput {
2021-07-19 09:52:51 +00:00
err = yqlib.NewStreamEvaluator().EvaluateNew(processExpression(args[0]), printer, "")
2022-01-27 04:54:26 +00:00
} else if pipingStdIn && args[0] != "-" && !maybeFile(args[0]) {
// must have given a single expression and piping input from stdin
err = allAtOnceEvaluator.EvaluateFiles(processExpression(args[0]), []string{"-"}, printer, leadingContentPreProcessing, decoder)
2020-11-13 02:19:54 +00:00
} else {
2021-12-21 04:02:07 +00:00
err = allAtOnceEvaluator.EvaluateFiles(processExpression(""), []string{args[0]}, printer, leadingContentPreProcessing, decoder)
2020-11-13 02:19:54 +00:00
}
default:
2021-12-21 04:02:07 +00:00
err = allAtOnceEvaluator.EvaluateFiles(processExpression(args[0]), args[1:], printer, leadingContentPreProcessing, decoder)
2020-11-13 02:19:54 +00:00
}
2020-11-29 09:25:47 +00:00
completedSuccessfully = err == nil
2020-11-30 05:35:21 +00:00
if err == nil && exitStatus && !printer.PrintedAnything() {
return errors.New("no matches found")
}
2020-11-13 02:19:54 +00:00
return err
}