github.com/tomwright/dasel@v1.27.3/internal/command/put_document_internal.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/spf13/cobra"
     6  	"github.com/tomwright/dasel/storage"
     7  	"io"
     8  	"os"
     9  )
    10  
    11  type putDocumentOpts struct {
    12  	File                string
    13  	Out                 string
    14  	ReadParser          string
    15  	WriteParser         string
    16  	Parser              string
    17  	Selector            string
    18  	DocumentFile        string
    19  	DocumentString      string
    20  	DocumentParser      string
    21  	Reader              io.Reader
    22  	Writer              io.Writer
    23  	Multi               bool
    24  	Compact             bool
    25  	MergeInputDocuments bool
    26  	EscapeHTML          bool
    27  }
    28  
    29  func readFileContents(path string) ([]byte, error) {
    30  	docFile, err := os.Open(path)
    31  	if err != nil {
    32  		return nil, fmt.Errorf("could not open file: %s: %w", path, err)
    33  	}
    34  	defer docFile.Close()
    35  
    36  	bytes, err := io.ReadAll(docFile)
    37  	if err != nil {
    38  		return nil, fmt.Errorf("could not read file: %s: %w", path, err)
    39  	}
    40  
    41  	return bytes, nil
    42  }
    43  
    44  func runPutDocumentCommand(opts putDocumentOpts, cmd *cobra.Command) error {
    45  	readParser, err := getReadParser(opts.File, opts.ReadParser, opts.Parser)
    46  	if err != nil {
    47  		return err
    48  	}
    49  	rootNode, err := getRootNode(getRootNodeOpts{
    50  		File:                opts.File,
    51  		Parser:              readParser,
    52  		Reader:              opts.Reader,
    53  		MergeInputDocuments: opts.MergeInputDocuments,
    54  	}, cmd)
    55  	if err != nil {
    56  		return err
    57  	}
    58  
    59  	documentParser, err := getPutDocumentParser(readParser, opts.DocumentParser)
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	if opts.DocumentFile != "" {
    65  		docFile, err := readFileContents(opts.DocumentFile)
    66  		if err != nil {
    67  			return err
    68  		}
    69  		opts.DocumentString = string(docFile)
    70  	}
    71  
    72  	documentValue, err := documentParser.FromBytes([]byte(opts.DocumentString))
    73  	if err != nil {
    74  		return fmt.Errorf("could not parse document: %w", err)
    75  	}
    76  
    77  	if opts.Multi {
    78  		if err := rootNode.PutMultiple(opts.Selector, documentValue); err != nil {
    79  			return fmt.Errorf("could not put document multi value: %w", err)
    80  		}
    81  	} else {
    82  		if err := rootNode.Put(opts.Selector, documentValue); err != nil {
    83  			return fmt.Errorf("could not put document value: %w", err)
    84  		}
    85  	}
    86  
    87  	writeParser, err := getWriteParser(readParser, opts.WriteParser, opts.Parser, opts.Out, opts.File, "")
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	writeOptions := []storage.ReadWriteOption{
    93  		storage.EscapeHTMLOption(opts.EscapeHTML),
    94  	}
    95  
    96  	if opts.Compact {
    97  		writeOptions = append(writeOptions, storage.PrettyPrintOption(false))
    98  	}
    99  
   100  	if err := writeNodeToOutput(writeNodeToOutputOpts{
   101  		Node:   rootNode,
   102  		Parser: writeParser,
   103  		File:   opts.File,
   104  		Out:    opts.Out,
   105  		Writer: opts.Writer,
   106  	}, cmd, writeOptions...); err != nil {
   107  		return fmt.Errorf("could not write output: %w", err)
   108  	}
   109  
   110  	return nil
   111  }
   112  
   113  func putDocumentCommand() *cobra.Command {
   114  	var documentParserFlag string
   115  
   116  	cmd := &cobra.Command{
   117  		Use:   "document -f <file> -d <document-parser> -s <selector> <document>",
   118  		Short: "Put an entire document into the given document.",
   119  		Args:  cobra.MinimumNArgs(1),
   120  		RunE: func(cmd *cobra.Command, args []string) error {
   121  			opts := putDocumentOpts{
   122  				File:           cmd.Flag("file").Value.String(),
   123  				Out:            cmd.Flag("out").Value.String(),
   124  				ReadParser:     cmd.Flag("read").Value.String(),
   125  				WriteParser:    cmd.Flag("write").Value.String(),
   126  				Parser:         cmd.Flag("parser").Value.String(),
   127  				Selector:       cmd.Flag("selector").Value.String(),
   128  				DocumentParser: documentParserFlag,
   129  			}
   130  			opts.Multi, _ = cmd.Flags().GetBool("multiple")
   131  			opts.Compact, _ = cmd.Flags().GetBool("compact")
   132  			opts.DocumentString, _ = cmd.Flags().GetString("value")
   133  			opts.DocumentFile, _ = cmd.Flags().GetString("value-file")
   134  			opts.MergeInputDocuments, _ = cmd.Flags().GetBool("merge-input-documents")
   135  			opts.EscapeHTML, _ = cmd.Flags().GetBool("escape-html")
   136  
   137  			if opts.Selector == "" && len(args) > 0 {
   138  				opts.Selector = args[0]
   139  				args = args[1:]
   140  			}
   141  
   142  			if opts.DocumentString == "" && opts.DocumentFile == "" && len(args) > 0 {
   143  				opts.DocumentString = args[0]
   144  				args = args[1:]
   145  			}
   146  
   147  			return runPutDocumentCommand(opts, cmd)
   148  		},
   149  	}
   150  
   151  	cmd.Flags().StringVarP(&documentParserFlag, "document-parser", "d", "", "The parser to use when reading the document")
   152  
   153  	return cmd
   154  }
   155  
   156  func getPutDocumentParser(readParser storage.ReadParser, documentParserFlag string) (storage.ReadParser, error) {
   157  	if documentParserFlag == "" {
   158  		return readParser, nil
   159  	}
   160  
   161  	parser, err := storage.NewReadParserFromString(documentParserFlag)
   162  	if err != nil {
   163  		return nil, fmt.Errorf("could not get document parser: %w", err)
   164  	}
   165  	return parser, nil
   166  }