mirror of
https://github.com/kopia/kopia.git
synced 2025-12-23 22:57:50 -05:00
- 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
125 lines
2.4 KiB
Go
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 "
|
|
}
|
|
}
|