forked from TrueCloudLab/restic
ls: include standard message_type
field in output
This commit is contained in:
parent
e44e4b00a6
commit
5dca8a70d5
5 changed files with 81 additions and 74 deletions
8
changelog/unreleased/pull-4664
Normal file
8
changelog/unreleased/pull-4664
Normal 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
|
|
@ -83,16 +83,18 @@ type jsonLsPrinter struct {
|
||||||
func (p *jsonLsPrinter) Snapshot(sn *restic.Snapshot) {
|
func (p *jsonLsPrinter) Snapshot(sn *restic.Snapshot) {
|
||||||
type lsSnapshot struct {
|
type lsSnapshot struct {
|
||||||
*restic.Snapshot
|
*restic.Snapshot
|
||||||
ID *restic.ID `json:"id"`
|
ID *restic.ID `json:"id"`
|
||||||
ShortID string `json:"short_id"`
|
ShortID string `json:"short_id"`
|
||||||
StructType string `json:"struct_type"` // "snapshot"
|
MessageType string `json:"message_type"` // "snapshot"
|
||||||
|
StructType string `json:"struct_type"` // "snapshot", deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.enc.Encode(lsSnapshot{
|
err := p.enc.Encode(lsSnapshot{
|
||||||
Snapshot: sn,
|
Snapshot: sn,
|
||||||
ID: sn.ID(),
|
ID: sn.ID(),
|
||||||
ShortID: sn.ID().Str(),
|
ShortID: sn.ID().Str(),
|
||||||
StructType: "snapshot",
|
MessageType: "snapshot",
|
||||||
|
StructType: "snapshot",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warnf("JSON encode failed: %v\n", err)
|
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"`
|
AccessTime time.Time `json:"atime,omitempty"`
|
||||||
ChangeTime time.Time `json:"ctime,omitempty"`
|
ChangeTime time.Time `json:"ctime,omitempty"`
|
||||||
Inode uint64 `json:"inode,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.
|
size uint64 // Target for Size pointer.
|
||||||
}{
|
}{
|
||||||
|
@ -137,6 +140,7 @@ func lsNodeJSON(enc *json.Encoder, path string, node *restic.Node) error {
|
||||||
AccessTime: node.AccessTime,
|
AccessTime: node.AccessTime,
|
||||||
ChangeTime: node.ChangeTime,
|
ChangeTime: node.ChangeTime,
|
||||||
Inode: node.Inode,
|
Inode: node.Inode,
|
||||||
|
MessageType: "node",
|
||||||
StructType: "node",
|
StructType: "node",
|
||||||
}
|
}
|
||||||
// Always print size for regular files, even when empty,
|
// Always print size for regular files, even when empty,
|
||||||
|
|
|
@ -87,11 +87,11 @@ var lsTestNodes = []lsTestNode{
|
||||||
|
|
||||||
func TestLsNodeJSON(t *testing.T) {
|
func TestLsNodeJSON(t *testing.T) {
|
||||||
for i, expect := range []string{
|
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":"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","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","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","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","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]
|
c := lsTestNodes[i]
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/restic/restic/internal/debug"
|
|
||||||
"github.com/restic/restic/internal/repository"
|
"github.com/restic/restic/internal/repository"
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
rtest "github.com/restic/restic/internal/test"
|
rtest "github.com/restic/restic/internal/test"
|
||||||
|
@ -160,11 +159,6 @@ func TestMount(t *testing.T) {
|
||||||
t.Skip("Skipping fuse tests")
|
t.Skip("Skipping fuse tests")
|
||||||
}
|
}
|
||||||
|
|
||||||
debugEnabled := debug.TestLogToStderr(t)
|
|
||||||
if debugEnabled {
|
|
||||||
defer debug.TestDisableLog(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
env, cleanup := withTestEnvironment(t)
|
env, cleanup := withTestEnvironment(t)
|
||||||
// must list snapshots more than once
|
// must list snapshots more than once
|
||||||
env.gopts.backendTestHook = nil
|
env.gopts.backendTestHook = nil
|
||||||
|
|
|
@ -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
|
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.
|
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
|
backup
|
||||||
------
|
------
|
||||||
|
|
||||||
|
@ -420,63 +417,67 @@ As an exception, the ``struct_type`` field is used to determine the message type
|
||||||
snapshot
|
snapshot
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``struct_type``| Always "snapshot" |
|
| ``message_type`` | Always "snapshot" |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``time`` | Timestamp of when the backup was started |
|
| ``struct_type`` | Always "snapshot" (deprecated) |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``parent`` | ID of the parent snapshot |
|
| ``time`` | Timestamp of when the backup was started |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``tree`` | ID of the root tree blob |
|
| ``parent`` | ID of the parent snapshot |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``paths`` | List of paths included in the backup |
|
| ``tree`` | ID of the root tree blob |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``hostname`` | Hostname of the backed up machine |
|
| ``paths`` | List of paths included in the backup |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``username`` | Username the backup command was run as |
|
| ``hostname`` | Hostname of the backed up machine |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``uid`` | ID of owner |
|
| ``username`` | Username the backup command was run as |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``gid`` | ID of group |
|
| ``uid`` | ID of owner |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``excludes`` | List of paths and globs excluded from the backup |
|
| ``gid`` | ID of group |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``tags`` | List of tags for the snapshot in question |
|
| ``excludes`` | List of paths and globs excluded from the backup |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``id`` | Snapshot ID |
|
| ``tags`` | List of tags for the snapshot in question |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| ``short_id`` | Snapshot ID, short form |
|
| ``id`` | Snapshot ID |
|
||||||
+----------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
| ``short_id`` | Snapshot ID, short form |
|
||||||
|
+------------------+--------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
node
|
node
|
||||||
^^^^
|
^^^^
|
||||||
|
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``struct_type`` | Always "node" |
|
| ``message_type`` | Always "node" |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``name`` | Node name |
|
| ``struct_type`` | Always "node" (deprecated) |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``type`` | Node type |
|
| ``name`` | Node name |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``path`` | Node path |
|
| ``type`` | Node type |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``uid`` | UID of node |
|
| ``path`` | Node path |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``gid`` | GID of node |
|
| ``uid`` | UID of node |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``size`` | Size in bytes |
|
| ``gid`` | GID of node |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``mode`` | Node mode |
|
| ``size`` | Size in bytes |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``atime`` | Node access time |
|
| ``mode`` | Node mode |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``mtime`` | Node modification time |
|
| ``atime`` | Node access time |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``ctime`` | Node creation time |
|
| ``mtime`` | Node modification time |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
| ``inode`` | Inode number of node |
|
| ``ctime`` | Node creation time |
|
||||||
+-----------------+--------------------------+
|
+------------------+----------------------------+
|
||||||
|
| ``inode`` | Inode number of node |
|
||||||
|
+------------------+----------------------------+
|
||||||
|
|
||||||
|
|
||||||
restore
|
restore
|
||||||
|
|
Loading…
Reference in a new issue