loadPatchFile reads and JSON-decodes a patch file from a relative path rooted at the runtime's FileIO. Returns ErrValidation on read or parse errors so the caller can surface a user-friendly message without leaking internal stack traces.
(runtime *common.RuntimeContext, path string)
| 507 | // errors so the caller can surface a user-friendly message without leaking |
| 508 | // internal stack traces. |
| 509 | func loadPatchFile(runtime *common.RuntimeContext, path string) (draftpkg.Patch, error) { |
| 510 | var patch draftpkg.Patch |
| 511 | if err := runtime.ValidatePath(path); err != nil { |
| 512 | return patch, mailValidationParamError("--patch-file", "--patch-file %q: %v", path, err).WithCause(mailInputStatError(err)) |
| 513 | } |
| 514 | f, err := runtime.FileIO().Open(path) |
| 515 | if err != nil { |
| 516 | return patch, mailValidationParamError("--patch-file", "--patch-file %q: %v", path, err).WithCause(mailInputStatError(err)) |
| 517 | } |
| 518 | defer f.Close() |
| 519 | data, err := io.ReadAll(f) |
| 520 | if err != nil { |
| 521 | return patch, mailValidationParamError("--patch-file", "read --patch-file %q: %v", path, err).WithCause(err) |
| 522 | } |
| 523 | if err := json.Unmarshal(data, &patch); err != nil { |
| 524 | return patch, mailValidationParamError("--patch-file", "parse patch file: %v", err).WithCause(err) |
| 525 | } |
| 526 | if err := patch.Validate(); err != nil { |
| 527 | return patch, mailValidationParamError("--patch-file", "validate patch file: %v", err).WithCause(err) |
| 528 | } |
| 529 | return patch, nil |
| 530 | } |
| 531 | |
| 532 | // buildDraftEditPatchTemplate returns the JSON template emitted by |
| 533 | // --print-patch-template. It documents the supported ops and field shapes so |