From a0c9db1d0970b0506342a434413f2a01c1f02831 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Tue, 15 Oct 2019 11:25:12 +0200 Subject: [PATCH] lib/api: Unify JSON marshalling of file infos (#6087) --- go.mod | 1 - lib/api/api.go | 72 ++++++++++++++++------------------ lib/db/set.go | 4 ++ lib/db/structs.go | 11 ++++++ lib/protocol/bep_extensions.go | 12 ++++++ 5 files changed, 60 insertions(+), 40 deletions(-) diff --git a/go.mod b/go.mod index 12710e17a..26cad7ba0 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,6 @@ require ( github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 - golang.org/x/sys v0.0.0-20190904154756-749cb33beabd // indirect golang.org/x/text v0.3.2 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect diff --git a/lib/api/api.go b/lib/api/api.go index e64ead42b..98618c3ad 100644 --- a/lib/api/api.go +++ b/lib/api/api.go @@ -1573,10 +1573,10 @@ func (s *service) getHeapProf(w http.ResponseWriter, r *http.Request) { pprof.WriteHeapProfile(w) } -func toJsonFileInfoSlice(fs []db.FileInfoTruncated) []jsonDBFileInfo { - res := make([]jsonDBFileInfo, len(fs)) +func toJsonFileInfoSlice(fs []db.FileInfoTruncated) []jsonFileInfoTrunc { + res := make([]jsonFileInfoTrunc, len(fs)) for i, f := range fs { - res[i] = jsonDBFileInfo(f) + res[i] = jsonFileInfoTrunc(f) } return res } @@ -1586,45 +1586,39 @@ func toJsonFileInfoSlice(fs []db.FileInfoTruncated) []jsonDBFileInfo { type jsonFileInfo protocol.FileInfo func (f jsonFileInfo) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]interface{}{ - "name": f.Name, - "type": f.Type, - "size": f.Size, - "permissions": fmt.Sprintf("%#o", f.Permissions), - "deleted": f.Deleted, - "invalid": protocol.FileInfo(f).IsInvalid(), - "ignored": protocol.FileInfo(f).IsIgnored(), - "mustRescan": protocol.FileInfo(f).MustRescan(), - "noPermissions": f.NoPermissions, - "modified": protocol.FileInfo(f).ModTime(), - "modifiedBy": f.ModifiedBy.String(), - "sequence": f.Sequence, - "numBlocks": len(f.Blocks), - "version": jsonVersionVector(f.Version), - "localFlags": f.LocalFlags, - }) + m := fileIntfJSONMap(protocol.FileInfo(f)) + m["numBlocks"] = len(f.Blocks) + return json.Marshal(m) } -type jsonDBFileInfo db.FileInfoTruncated +type jsonFileInfoTrunc db.FileInfoTruncated -func (f jsonDBFileInfo) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]interface{}{ - "name": f.Name, - "type": f.Type.String(), - "size": f.Size, - "permissions": fmt.Sprintf("%#o", f.Permissions), - "deleted": f.Deleted, - "invalid": db.FileInfoTruncated(f).IsInvalid(), - "ignored": db.FileInfoTruncated(f).IsIgnored(), - "mustRescan": db.FileInfoTruncated(f).MustRescan(), - "noPermissions": f.NoPermissions, - "modified": db.FileInfoTruncated(f).ModTime(), - "modifiedBy": f.ModifiedBy.String(), - "sequence": f.Sequence, - "numBlocks": nil, // explicitly unknown - "version": jsonVersionVector(f.Version), - "localFlags": f.LocalFlags, - }) +func (f jsonFileInfoTrunc) MarshalJSON() ([]byte, error) { + m := fileIntfJSONMap(db.FileInfoTruncated(f)) + m["numBlocks"] = nil // explicitly unknown + return json.Marshal(m) +} + +func fileIntfJSONMap(f db.FileIntf) map[string]interface{} { + out := map[string]interface{}{ + "name": f.FileName(), + "type": f.FileType().String(), + "size": f.FileSize(), + "deleted": f.IsDeleted(), + "invalid": f.IsInvalid(), + "ignored": f.IsIgnored(), + "mustRescan": f.MustRescan(), + "noPermissions": !f.HasPermissionBits(), + "modified": f.ModTime(), + "modifiedBy": f.FileModifiedBy().String(), + "sequence": f.SequenceNo(), + "version": jsonVersionVector(f.FileVersion()), + "localFlags": f.FileLocalFlags(), + } + if f.HasPermissionBits() { + out["permissions"] = fmt.Sprintf("%#o", f.FilePermissions()) + } + return out } type jsonVersionVector protocol.Vector diff --git a/lib/db/set.go b/lib/db/set.go index cdd409d5b..3b3a9dbdd 100644 --- a/lib/db/set.go +++ b/lib/db/set.go @@ -51,6 +51,10 @@ type FileIntf interface { SequenceNo() int64 BlockSize() int FileVersion() protocol.Vector + FileType() protocol.FileInfoType + FilePermissions() uint32 + FileModifiedBy() protocol.ShortID + ModTime() time.Time } // The Iterator is called with either a protocol.FileInfo or a diff --git a/lib/db/structs.go b/lib/db/structs.go index 4472bbbfb..f417d002b 100644 --- a/lib/db/structs.go +++ b/lib/db/structs.go @@ -116,6 +116,17 @@ func (f FileInfoTruncated) FileVersion() protocol.Vector { return f.Version } +func (f FileInfoTruncated) FileType() protocol.FileInfoType { + return f.Type +} + +func (f FileInfoTruncated) FilePermissions() uint32 { + return f.Permissions +} + +func (f FileInfoTruncated) FileModifiedBy() protocol.ShortID { + return f.ModifiedBy +} func (f FileInfoTruncated) ConvertToIgnoredFileInfo(by protocol.ShortID) protocol.FileInfo { return protocol.FileInfo{ Name: f.Name, diff --git a/lib/protocol/bep_extensions.go b/lib/protocol/bep_extensions.go index b19b14a19..bb2298014 100644 --- a/lib/protocol/bep_extensions.go +++ b/lib/protocol/bep_extensions.go @@ -124,6 +124,18 @@ func (f FileInfo) FileVersion() Vector { return f.Version } +func (f FileInfo) FileType() FileInfoType { + return f.Type +} + +func (f FileInfo) FilePermissions() uint32 { + return f.Permissions +} + +func (f FileInfo) FileModifiedBy() ShortID { + return f.ModifiedBy +} + // WinsConflict returns true if "f" is the one to choose when it is in // conflict with "other". func (f FileInfo) WinsConflict(other FileInfo) bool {