Files
kopia/cli/json_output.go
Julio Lopez ab1f62e3ad refactor(general): misc cleanups (#4615)
- nit: rename var to packCountByPrefix
- leverage impossible package
- use maps.Clone
- unexport indirectObjectID
- unexport compressed
- rename function to flushBufferLocked
- add checklocks annotations to functions that must be called under w.mu
2025-05-29 08:26:55 -07:00

125 lines
2.4 KiB
Go

package cli
import (
"encoding/json"
"fmt"
"io"
"github.com/alecthomas/kingpin/v2"
"github.com/kopia/kopia/internal/impossible"
"github.com/kopia/kopia/snapshot"
)
type jsonOutput struct {
jsonOutput bool
jsonIndent bool
jsonVerbose bool // output non-essential stats as part of JSON
out io.Writer
}
func (c *jsonOutput) setup(svc appServices, cmd *kingpin.CmdClause) {
cmd.Flag("json", "Output result in JSON format to stdout").BoolVar(&c.jsonOutput)
cmd.Flag("json-indent", "Output result in indented JSON format to stdout").Hidden().BoolVar(&c.jsonIndent)
cmd.Flag("json-verbose", "Output non-essential data (e.g. statistics) in JSON format").Hidden().BoolVar(&c.jsonVerbose)
c.out = svc.stdout()
}
func (c *jsonOutput) cleanupSnapshotManifestForJSON(v *snapshot.Manifest) any {
m := *v
if !c.jsonVerbose {
return struct {
*snapshot.Manifest
// trick to remove 'stats' completely.
Stats string `json:"stats,omitempty"`
}{Manifest: v}
}
return &m
}
func (c *jsonOutput) cleanupSnapshotManifestListForJSON(manifests []*snapshot.Manifest) any {
var res []any
for _, m := range manifests {
res = append(res, c.cleanupSnapshotManifestForJSON(m))
}
return res
}
func (c *jsonOutput) cleanupForJSON(v any) any {
switch v := v.(type) {
case *snapshot.Manifest:
return c.cleanupSnapshotManifestForJSON(v)
case []*snapshot.Manifest:
return c.cleanupSnapshotManifestListForJSON(v)
default:
return v
}
}
func (c *jsonOutput) jsonBytes(v any) []byte {
return c.jsonIndentedBytes(v, "")
}
func (c *jsonOutput) jsonIndentedBytes(v any, indent string) []byte {
v = c.cleanupForJSON(v)
var (
b []byte
err error
)
if c.jsonIndent {
b, err = json.MarshalIndent(v, indent+"", indent+" ")
} else {
b, err = json.Marshal(v)
}
impossible.PanicOnError(err)
return b
}
type jsonList struct {
separator string
o *jsonOutput
}
func (l *jsonList) begin(o *jsonOutput) {
l.o = o
if o.jsonOutput {
fmt.Fprint(l.o.out, "[") //nolint:errcheck
if !o.jsonIndent {
l.separator = "\n "
}
}
}
func (l *jsonList) end() {
if l.o.jsonOutput {
if !l.o.jsonIndent {
fmt.Fprint(l.o.out, "\n") //nolint:errcheck
}
fmt.Fprint(l.o.out, "]") //nolint:errcheck
}
}
func (l *jsonList) emit(v any) {
fmt.Fprintf(l.o.out, "%s%s", l.separator, l.o.jsonBytes(v)) //nolint:errcheck
if l.o.jsonIndent {
l.separator = ","
} else {
l.separator = ",\n "
}
}