setmeta updates to support json files (or reading stdin). easier interop with getmeta (#1240)

This commit is contained in:
Mike Sawka 2024-11-08 10:19:57 -08:00 committed by GitHub
parent fb641ac717
commit b36a7df929
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -6,6 +6,8 @@ package cmd
import (
"encoding/json"
"fmt"
"io"
"os"
"strconv"
"strings"
@ -14,15 +16,46 @@ import (
)
var setMetaCmd = &cobra.Command{
Use: "setmeta {blockid|blocknum|this} key=value ...",
Use: "setmeta [-b {blockid|blocknum|this}] [--json file.json] key=value ...",
Short: "set metadata for an entity",
Args: cobra.MinimumNArgs(1),
Args: cobra.MinimumNArgs(0),
Run: setMetaRun,
PreRunE: preRunSetupRpcClient,
}
var setMetaJsonFilePath string
func init() {
rootCmd.AddCommand(setMetaCmd)
setMetaCmd.Flags().StringVar(&setMetaJsonFilePath, "json", "", "JSON file containing metadata to apply (use '-' for stdin)")
}
func loadJSONFile(filepath string) (map[string]interface{}, error) {
var data []byte
var err error
if filepath == "-" {
data, err = io.ReadAll(os.Stdin)
if err != nil {
return nil, fmt.Errorf("reading from stdin: %v", err)
}
} else {
data, err = os.ReadFile(filepath)
if err != nil {
return nil, fmt.Errorf("reading JSON file: %v", err)
}
}
var result map[string]interface{}
if err := json.Unmarshal(data, &result); err != nil {
return nil, fmt.Errorf("parsing JSON file: %v", err)
}
if result == nil {
return nil, fmt.Errorf("JSON file must contain an object, not null")
}
return result, nil
}
func parseMetaSets(metaSets []string) (map[string]interface{}, error) {
@ -39,7 +72,7 @@ func parseMetaSets(metaSets []string) (map[string]interface{}, error) {
meta[fields[0]] = true
} else if setVal == "false" {
meta[fields[0]] = false
} else if setVal[0] == '[' || setVal[0] == '{' {
} else if setVal[0] == '[' || setVal[0] == '{' || setVal[0] == '"' {
var val interface{}
err := json.Unmarshal([]byte(setVal), &val)
if err != nil {
@ -63,31 +96,63 @@ func parseMetaSets(metaSets []string) (map[string]interface{}, error) {
return meta, nil
}
func simpleMergeMeta(meta map[string]interface{}, metaUpdate map[string]interface{}) map[string]interface{} {
for k, v := range metaUpdate {
if v == nil {
delete(meta, k)
} else {
meta[k] = v
}
}
return meta
}
func setMetaRun(cmd *cobra.Command, args []string) {
oref := blockArg
metaSetsStrs := args[:]
if oref == "" {
WriteStderr("[error] oref is required\n")
if blockArg == "" {
WriteStderr("[error] block (oref) is required\n")
return
}
err := validateEasyORef(oref)
err := validateEasyORef(blockArg)
if err != nil {
WriteStderr("[error] %v\n", err)
return
}
meta, err := parseMetaSets(metaSetsStrs)
var jsonMeta map[string]interface{}
if setMetaJsonFilePath != "" {
jsonMeta, err = loadJSONFile(setMetaJsonFilePath)
if err != nil {
WriteStderr("[error] %v\n", err)
return
}
fullORef, err := resolveSimpleId(oref)
}
cmdMeta, err := parseMetaSets(args)
if err != nil {
WriteStderr("[error] %v\n", err)
return
}
// Merge JSON metadata with command-line metadata, with command-line taking precedence
var fullMeta map[string]any
if len(jsonMeta) > 0 {
fullMeta = simpleMergeMeta(jsonMeta, cmdMeta)
} else {
fullMeta = cmdMeta
}
if len(fullMeta) == 0 {
WriteStderr("[error] no metadata keys specified\n")
return
}
fullORef, err := resolveSimpleId(blockArg)
if err != nil {
WriteStderr("[error] resolving oref: %v\n", err)
return
}
setMetaWshCmd := &wshrpc.CommandSetMetaData{
ORef: *fullORef,
Meta: meta,
Meta: fullMeta,
}
_, err = RpcClient.SendRpcRequest(wshrpc.Command_SetMeta, setMetaWshCmd, &wshrpc.RpcOpts{Timeout: 2000})
if err != nil {