a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
64 lines
1.8 KiB
Go
64 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// readStructuredArg resolves a JSON argument from, in precedence order:
|
|
//
|
|
// 1. the inline value, when non-empty and not "-"
|
|
// 2. the file path, when non-empty
|
|
// 3. stdin, when the inline value is exactly "-"
|
|
//
|
|
// It is the shared lowering primitive for the edit verb's JSON-shaped
|
|
// parameters (verify_change's changes, preview_edit's workspace_edit,
|
|
// simulate_chain's steps, batch_edit's edits, change_contract's ranges).
|
|
// The returned value is the verbatim JSON bytes (validated as syntactically
|
|
// well-formed JSON); the caller decides whether to forward it as a string or
|
|
// a parsed value. An empty result (no source provided) returns (nil, nil) so
|
|
// the caller can decide whether the argument is required.
|
|
//
|
|
// stdinReader is injected so tests can drive the "-" path without touching
|
|
// the process's real stdin; nil falls back to os.Stdin.
|
|
func readStructuredArg(inline, file string, stdinReader io.Reader) (json.RawMessage, error) {
|
|
var (
|
|
data []byte
|
|
source string
|
|
)
|
|
switch {
|
|
case inline == "-":
|
|
r := stdinReader
|
|
if r == nil {
|
|
r = os.Stdin
|
|
}
|
|
b, err := io.ReadAll(r)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("reading JSON from stdin: %w", err)
|
|
}
|
|
data, source = b, "stdin"
|
|
case inline != "":
|
|
data, source = []byte(inline), "inline JSON"
|
|
case file != "":
|
|
b, err := os.ReadFile(file)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("reading JSON file %s: %w", file, err)
|
|
}
|
|
data, source = b, fmt.Sprintf("file %s", file)
|
|
default:
|
|
return nil, nil
|
|
}
|
|
|
|
trimmed := strings.TrimSpace(string(data))
|
|
if trimmed == "" {
|
|
return nil, fmt.Errorf("%s is empty", source)
|
|
}
|
|
if !json.Valid([]byte(trimmed)) {
|
|
return nil, fmt.Errorf("%s is not valid JSON", source)
|
|
}
|
|
return json.RawMessage(trimmed), nil
|
|
}
|