From a58a8f2ce0f536bc7c9d4696b3b688fdcebd1cbd Mon Sep 17 00:00:00 2001 From: Dark Dragon Date: Mon, 30 Dec 2024 22:33:01 +0100 Subject: [PATCH] Add JSON output to check command --- changelog/unreleased/issue-1378 | 7 +++++ cmd/restic/cmd_check.go | 50 ++++++++++++++++++++++++++++++++- doc/075_scripting.rst | 12 ++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 changelog/unreleased/issue-1378 diff --git a/changelog/unreleased/issue-1378 b/changelog/unreleased/issue-1378 new file mode 100644 index 000000000..fd5d379cc --- /dev/null +++ b/changelog/unreleased/issue-1378 @@ -0,0 +1,7 @@ +Enhancement: Add JSON support to check + +Restic `check` now also supports the `--json` option and gives all +statistics in JSON format. + +https://github.com/restic/restic/issues/1378 +https://github.com/restic/restic/pull/5194 diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index 3ae79149e..765e93744 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -2,6 +2,7 @@ package main import ( "context" + "fmt" "math/rand" "os" "strconv" @@ -215,7 +216,12 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args return errors.Fatal("the check command expects no arguments, only options - please see `restic help check` for usage and flags") } - printer := newTerminalProgressPrinter(gopts.verbosity, term) + var printer progress.Printer + if !gopts.JSON { + printer = newTerminalProgressPrinter(gopts.verbosity, term) + } else { + printer = newJSONErrorPrinter(term) + } cleanup := prepareCheckCache(opts, &gopts, printer) defer cleanup() @@ -431,6 +437,13 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args return errors.Fatal("repository contains errors") } printer.P("no errors were found\n") + if gopts.JSON { + status := checkSuccess{ + MessageType: "checked", + Message: "no errors were found", + } + term.Print(ui.ToJSONString(status)) + } return nil } @@ -478,3 +491,38 @@ func selectRandomPacksByFileSize(allPacks map[restic.ID]int64, subsetSize int64, packs := selectRandomPacksByPercentage(allPacks, subsetPercentage) return packs } + +type checkSuccess struct { + MessageType string `json:"message_type"` // "checked" + Message string `json:"message"` +} + +type checkError struct { + MessageType string `json:"message_type"` // "error" + Message string `json:"message"` +} + +type jsonErrorPrinter struct { + term ui.Terminal +} + +func newJSONErrorPrinter(term ui.Terminal) *jsonErrorPrinter { + return &jsonErrorPrinter{ + term: term, + } +} + +func (*jsonErrorPrinter) NewCounter(_ string) *progress.Counter { + return nil +} + +func (p *jsonErrorPrinter) E(msg string, args ...interface{}) { + status := checkError{ + MessageType: "error", + Message: fmt.Sprintf(msg, args...), + } + p.term.Print(ui.ToJSONString(status)) +} +func (*jsonErrorPrinter) P(_ string, _ ...interface{}) {} +func (*jsonErrorPrinter) V(_ string, _ ...interface{}) {} +func (*jsonErrorPrinter) VV(_ string, _ ...interface{}) {} diff --git a/doc/075_scripting.rst b/doc/075_scripting.rst index 57a8e2872..3cc009c15 100644 --- a/doc/075_scripting.rst +++ b/doc/075_scripting.rst @@ -245,6 +245,18 @@ are stored in JSON form. Specifying ``--json`` or ``--quiet`` will suppress any non-JSON messages the command generates. +check +----- + +The ``check`` command outputs JSON messages with the following format: + ++------------------+--------------------------------+ +| ``message_type`` | Either "checked" or "error" | ++------------------+--------------------------------+ +| ``message`` | Descriptive message | ++------------------+--------------------------------+ + + diff ----