Merge pull request #4664 from MichaelEischer/ls-unified-json-output

ls: include standard `message_type` field in output
This commit is contained in:
Michael Eischer 2024-02-18 15:47:41 +00:00 committed by GitHub
commit 80754dbf0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 81 additions and 74 deletions

View File

@ -0,0 +1,8 @@
Enhancement: `ls` uses `message_type` field to distinguish JSON messages
The `ls` command was the only command that used the `struct_type` field to determine
the message type in the JSON output format. Now, the JSON output of the
`ls` command also includes the `message_type`. The `struct_type` field is
still included, but it deprecated.
https://github.com/restic/restic/pull/4664

View File

@ -83,16 +83,18 @@ type jsonLsPrinter struct {
func (p *jsonLsPrinter) Snapshot(sn *restic.Snapshot) {
type lsSnapshot struct {
*restic.Snapshot
ID *restic.ID `json:"id"`
ShortID string `json:"short_id"`
StructType string `json:"struct_type"` // "snapshot"
ID *restic.ID `json:"id"`
ShortID string `json:"short_id"`
MessageType string `json:"message_type"` // "snapshot"
StructType string `json:"struct_type"` // "snapshot", deprecated
}
err := p.enc.Encode(lsSnapshot{
Snapshot: sn,
ID: sn.ID(),
ShortID: sn.ID().Str(),
StructType: "snapshot",
Snapshot: sn,
ID: sn.ID(),
ShortID: sn.ID().Str(),
MessageType: "snapshot",
StructType: "snapshot",
})
if err != nil {
Warnf("JSON encode failed: %v\n", err)
@ -121,7 +123,8 @@ func lsNodeJSON(enc *json.Encoder, path string, node *restic.Node) error {
AccessTime time.Time `json:"atime,omitempty"`
ChangeTime time.Time `json:"ctime,omitempty"`
Inode uint64 `json:"inode,omitempty"`
StructType string `json:"struct_type"` // "node"
MessageType string `json:"message_type"` // "node"
StructType string `json:"struct_type"` // "node", deprecated
size uint64 // Target for Size pointer.
}{
@ -137,6 +140,7 @@ func lsNodeJSON(enc *json.Encoder, path string, node *restic.Node) error {
AccessTime: node.AccessTime,
ChangeTime: node.ChangeTime,
Inode: node.Inode,
MessageType: "node",
StructType: "node",
}
// Always print size for regular files, even when empty,

View File

@ -87,11 +87,11 @@ var lsTestNodes = []lsTestNode{
func TestLsNodeJSON(t *testing.T) {
for i, expect := range []string{
`{"name":"baz","type":"file","path":"/bar/baz","uid":10000000,"gid":20000000,"size":12345,"permissions":"----------","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","struct_type":"node"}`,
`{"name":"empty","type":"file","path":"/foo/empty","uid":1001,"gid":1001,"size":0,"permissions":"----------","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","struct_type":"node"}`,
`{"name":"link","type":"symlink","path":"/foo/link","uid":0,"gid":0,"mode":134218239,"permissions":"Lrwxrwxrwx","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","struct_type":"node"}`,
`{"name":"directory","type":"dir","path":"/some/directory","uid":0,"gid":0,"mode":2147484141,"permissions":"drwxr-xr-x","mtime":"2020-01-02T03:04:05Z","atime":"2021-02-03T04:05:06.000000007Z","ctime":"2022-03-04T05:06:07.000000008Z","struct_type":"node"}`,
`{"name":"sticky","type":"dir","path":"/some/sticky","uid":0,"gid":0,"mode":2161115629,"permissions":"dugtrwxr-xr-x","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","struct_type":"node"}`,
`{"name":"baz","type":"file","path":"/bar/baz","uid":10000000,"gid":20000000,"size":12345,"permissions":"----------","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","message_type":"node","struct_type":"node"}`,
`{"name":"empty","type":"file","path":"/foo/empty","uid":1001,"gid":1001,"size":0,"permissions":"----------","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","message_type":"node","struct_type":"node"}`,
`{"name":"link","type":"symlink","path":"/foo/link","uid":0,"gid":0,"mode":134218239,"permissions":"Lrwxrwxrwx","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","message_type":"node","struct_type":"node"}`,
`{"name":"directory","type":"dir","path":"/some/directory","uid":0,"gid":0,"mode":2147484141,"permissions":"drwxr-xr-x","mtime":"2020-01-02T03:04:05Z","atime":"2021-02-03T04:05:06.000000007Z","ctime":"2022-03-04T05:06:07.000000008Z","message_type":"node","struct_type":"node"}`,
`{"name":"sticky","type":"dir","path":"/some/sticky","uid":0,"gid":0,"mode":2161115629,"permissions":"dugtrwxr-xr-x","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","message_type":"node","struct_type":"node"}`,
} {
c := lsTestNodes[i]
buf := new(bytes.Buffer)

View File

@ -12,7 +12,6 @@ import (
"testing"
"time"
"github.com/restic/restic/internal/debug"
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test"
@ -160,11 +159,6 @@ func TestMount(t *testing.T) {
t.Skip("Skipping fuse tests")
}
debugEnabled := debug.TestLogToStderr(t)
if debugEnabled {
defer debug.TestDisableLog(t)
}
env, cleanup := withTestEnvironment(t)
// must list snapshots more than once
env.gopts.backendTestHook = nil

View File

@ -75,9 +75,6 @@ Several commands, in particular long running ones or those that generate a large
use a format also known as JSON lines. It consists of a stream of new-line separated JSON
messages. You can determine the nature of the message using the ``message_type`` field.
As an exception, the ``ls`` command uses the field ``struct_type`` instead.
backup
------
@ -420,63 +417,67 @@ As an exception, the ``struct_type`` field is used to determine the message type
snapshot
^^^^^^^^
+----------------+--------------------------------------------------+
| ``struct_type``| Always "snapshot" |
+----------------+--------------------------------------------------+
| ``time`` | Timestamp of when the backup was started |
+----------------+--------------------------------------------------+
| ``parent`` | ID of the parent snapshot |
+----------------+--------------------------------------------------+
| ``tree`` | ID of the root tree blob |
+----------------+--------------------------------------------------+
| ``paths`` | List of paths included in the backup |
+----------------+--------------------------------------------------+
| ``hostname`` | Hostname of the backed up machine |
+----------------+--------------------------------------------------+
| ``username`` | Username the backup command was run as |
+----------------+--------------------------------------------------+
| ``uid`` | ID of owner |
+----------------+--------------------------------------------------+
| ``gid`` | ID of group |
+----------------+--------------------------------------------------+
| ``excludes`` | List of paths and globs excluded from the backup |
+----------------+--------------------------------------------------+
| ``tags`` | List of tags for the snapshot in question |
+----------------+--------------------------------------------------+
| ``id`` | Snapshot ID |
+----------------+--------------------------------------------------+
| ``short_id`` | Snapshot ID, short form |
+----------------+--------------------------------------------------+
+------------------+--------------------------------------------------+
| ``message_type`` | Always "snapshot" |
+------------------+--------------------------------------------------+
| ``struct_type`` | Always "snapshot" (deprecated) |
+------------------+--------------------------------------------------+
| ``time`` | Timestamp of when the backup was started |
+------------------+--------------------------------------------------+
| ``parent`` | ID of the parent snapshot |
+------------------+--------------------------------------------------+
| ``tree`` | ID of the root tree blob |
+------------------+--------------------------------------------------+
| ``paths`` | List of paths included in the backup |
+------------------+--------------------------------------------------+
| ``hostname`` | Hostname of the backed up machine |
+------------------+--------------------------------------------------+
| ``username`` | Username the backup command was run as |
+------------------+--------------------------------------------------+
| ``uid`` | ID of owner |
+------------------+--------------------------------------------------+
| ``gid`` | ID of group |
+------------------+--------------------------------------------------+
| ``excludes`` | List of paths and globs excluded from the backup |
+------------------+--------------------------------------------------+
| ``tags`` | List of tags for the snapshot in question |
+------------------+--------------------------------------------------+
| ``id`` | Snapshot ID |
+------------------+--------------------------------------------------+
| ``short_id`` | Snapshot ID, short form |
+------------------+--------------------------------------------------+
node
^^^^
+-----------------+--------------------------+
| ``struct_type`` | Always "node" |
+-----------------+--------------------------+
| ``name`` | Node name |
+-----------------+--------------------------+
| ``type`` | Node type |
+-----------------+--------------------------+
| ``path`` | Node path |
+-----------------+--------------------------+
| ``uid`` | UID of node |
+-----------------+--------------------------+
| ``gid`` | GID of node |
+-----------------+--------------------------+
| ``size`` | Size in bytes |
+-----------------+--------------------------+
| ``mode`` | Node mode |
+-----------------+--------------------------+
| ``atime`` | Node access time |
+-----------------+--------------------------+
| ``mtime`` | Node modification time |
+-----------------+--------------------------+
| ``ctime`` | Node creation time |
+-----------------+--------------------------+
| ``inode`` | Inode number of node |
+-----------------+--------------------------+
+------------------+----------------------------+
| ``message_type`` | Always "node" |
+------------------+----------------------------+
| ``struct_type`` | Always "node" (deprecated) |
+------------------+----------------------------+
| ``name`` | Node name |
+------------------+----------------------------+
| ``type`` | Node type |
+------------------+----------------------------+
| ``path`` | Node path |
+------------------+----------------------------+
| ``uid`` | UID of node |
+------------------+----------------------------+
| ``gid`` | GID of node |
+------------------+----------------------------+
| ``size`` | Size in bytes |
+------------------+----------------------------+
| ``mode`` | Node mode |
+------------------+----------------------------+
| ``atime`` | Node access time |
+------------------+----------------------------+
| ``mtime`` | Node modification time |
+------------------+----------------------------+
| ``ctime`` | Node creation time |
+------------------+----------------------------+
| ``inode`` | Inode number of node |
+------------------+----------------------------+
restore