@cryptotaxi247 / kubo / commits / eaa19388d

Implement Object API

This commit was moved from ipfs/go-ipfs-http-client@38149e46c8c3a1544dc3e3108ef72ffbc885e410

Łukasz Magiera committed Jan 15, 2019 at 16:31 UTC eaa19388d4d86eebf09d93a3a637e0690df722bd
5 files changed +208 -31
client/httpapi/block.go
+1 -1
@@ -67,7 +67,7 @@ func (api *BlockAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.BlockP
67 }
68
69 func (api *BlockAPI) Get(ctx context.Context, p iface.Path) (io.Reader, error) {
70 - resp, err := api.core().request("block/get", p.String()).Send(context.Background())
70 + resp, err := api.core().request("block/get", p.String()).Send(ctx)
71 if err != nil {
72 return nil, err
73 }
client/httpapi/ipldnode.go
+3 -4
@@ -3,7 +3,6 @@ package httpapi
3 import (
4 "context"
5 "errors"
6 - "fmt"
6 "io/ioutil"
7 "strconv"
8
@@ -20,11 +19,11 @@ type ipldNode struct {
19 api *HttpApi
20 }
21
23 -func (a *HttpApi) nodeFromPath(ctx context.Context, p iface.ResolvedPath) ipld.Node {
22 +func (api *HttpApi) nodeFromPath(ctx context.Context, p iface.ResolvedPath) ipld.Node {
23 return &ipldNode{
24 ctx: ctx,
25 path: p,
27 - api: a,
26 + api: api,
27 }
28 }
29
@@ -47,7 +46,7 @@ func (n *ipldNode) Cid() cid.Cid {
46 }
47
48 func (n *ipldNode) String() string {
50 - return fmt.Sprintf("[Block %s]", n.Cid())
49 + return n.Cid().String()
50 }
51
52 func (n *ipldNode) Loggable() map[string]interface{} {
client/httpapi/key.go
+4 -4
@@ -59,10 +59,10 @@ func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, o
59 return nil, false, err
60 }
61
62 - var out struct{
63 - Was string
64 - Now string
65 - Id string
62 + var out struct {
63 + Was string
64 + Now string
65 + Id string
66 Overwrite bool
67 }
68 err = api.core().request("key/rename", oldName, newName).
client/httpapi/object.go
+197 -19
@@ -1,14 +1,17 @@
1 package httpapi
2
3 import (
4 + "bytes"
5 "context"
5 - "github.com/ipfs/go-cid"
6 "io"
7 + "io/ioutil"
8
9 "github.com/ipfs/go-ipfs/core/coreapi/interface"
10 caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
11
12 + "github.com/ipfs/go-cid"
13 "github.com/ipfs/go-ipld-format"
14 + "github.com/ipfs/go-merkledag"
15 )
16
17 type ObjectAPI HttpApi
@@ -37,44 +40,219 @@ func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (
40 return api.core().nodeFromPath(ctx, iface.IpfsPath(c)), nil
41 }
42
40 -func (api *ObjectAPI) Put(context.Context, io.Reader, ...caopts.ObjectPutOption) (iface.ResolvedPath, error) {
41 - panic("implement me")
43 +func (api *ObjectAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.ObjectPutOption) (iface.ResolvedPath, error) {
44 + options, err := caopts.ObjectPutOptions(opts...)
45 + if err != nil {
46 + return nil, err
47 + }
48 +
49 + var out objectOut
50 + err = api.core().request("object/put").
51 + Option("inputenc", options.InputEnc).
52 + Option("datafieldenc", options.DataType).
53 + Option("pin", options.Pin).
54 + FileBody(r).
55 + Exec(ctx, &out)
56 + if err != nil {
57 + return nil, err
58 + }
59 +
60 + c, err := cid.Parse(out.Hash)
61 + if err != nil {
62 + return nil, err
63 + }
64 +
65 + return iface.IpfsPath(c), nil
66 }
67
44 -func (api *ObjectAPI) Get(context.Context, iface.Path) (format.Node, error) {
45 - panic("implement me")
68 +func (api *ObjectAPI) Get(ctx context.Context, p iface.Path) (format.Node, error) {
69 + r, err := api.core().Block().Get(ctx, p)
70 + if err != nil {
71 + return nil, err
72 + }
73 + b, err := ioutil.ReadAll(r)
74 + if err != nil {
75 + return nil, err
76 + }
77 +
78 + return merkledag.DecodeProtobuf(b)
79 }
80
48 -func (api *ObjectAPI) Data(context.Context, iface.Path) (io.Reader, error) {
49 - panic("implement me")
81 +func (api *ObjectAPI) Data(ctx context.Context, p iface.Path) (io.Reader, error) {
82 + resp, err := api.core().request("object/data", p.String()).Send(ctx)
83 + if err != nil {
84 + return nil, err
85 + }
86 + if resp.Error != nil {
87 + return nil, resp.Error
88 + }
89 +
90 + //TODO: make Data return ReadCloser to avoid copying
91 + defer resp.Close()
92 + b := new(bytes.Buffer)
93 + if _, err := io.Copy(b, resp.Output); err != nil {
94 + return nil, err
95 + }
96 +
97 + return b, nil
98 }
99
52 -func (api *ObjectAPI) Links(context.Context, iface.Path) ([]*format.Link, error) {
53 - panic("implement me")
100 +func (api *ObjectAPI) Links(ctx context.Context, p iface.Path) ([]*format.Link, error) {
101 + var out struct {
102 + Links []struct {
103 + Name string
104 + Hash string
105 + Size uint64
106 + }
107 + }
108 + if err := api.core().request("object/links", p.String()).Exec(ctx, &out); err != nil {
109 + return nil, err
110 + }
111 + res := make([]*format.Link, len(out.Links))
112 + for i, l := range out.Links {
113 + c, err := cid.Parse(l.Hash)
114 + if err != nil {
115 + return nil, err
116 + }
117 +
118 + res[i] = &format.Link{
119 + Cid: c,
120 + Name: l.Name,
121 + Size: l.Size,
122 + }
123 + }
124 +
125 + return res, nil
126 }
127
56 -func (api *ObjectAPI) Stat(context.Context, iface.Path) (*iface.ObjectStat, error) {
57 - panic("implement me")
128 +func (api *ObjectAPI) Stat(ctx context.Context, p iface.Path) (*iface.ObjectStat, error) {
129 + var out struct {
130 + Hash string
131 + NumLinks int
132 + BlockSize int
133 + LinksSize int
134 + DataSize int
135 + CumulativeSize int
136 + }
137 + if err := api.core().request("object/stat", p.String()).Exec(ctx, &out); err != nil {
138 + return nil, err
139 + }
140 +
141 + c, err := cid.Parse(out.Hash)
142 + if err != nil {
143 + return nil, err
144 + }
145 +
146 + return &iface.ObjectStat{
147 + Cid: c,
148 + NumLinks: out.NumLinks,
149 + BlockSize: out.BlockSize,
150 + LinksSize: out.LinksSize,
151 + DataSize: out.DataSize,
152 + CumulativeSize: out.CumulativeSize,
153 + }, nil
154 }
155
156 func (api *ObjectAPI) AddLink(ctx context.Context, base iface.Path, name string, child iface.Path, opts ...caopts.ObjectAddLinkOption) (iface.ResolvedPath, error) {
61 - panic("implement me")
157 + options, err := caopts.ObjectAddLinkOptions(opts...)
158 + if err != nil {
159 + return nil, err
160 + }
161 +
162 + var out objectOut
163 + err = api.core().request("object/patch/add-link", base.String(), name, child.String()).
164 + Option("create", options.Create).
165 + Exec(ctx, &out)
166 + if err != nil {
167 + return nil, err
168 + }
169 +
170 + c, err := cid.Parse(out.Hash)
171 + if err != nil {
172 + return nil, err
173 + }
174 +
175 + return iface.IpfsPath(c), nil
176 }
177
178 func (api *ObjectAPI) RmLink(ctx context.Context, base iface.Path, link string) (iface.ResolvedPath, error) {
65 - panic("implement me")
179 + var out objectOut
180 + err := api.core().request("object/patch/rm-link", base.String(), link).
181 + Exec(ctx, &out)
182 + if err != nil {
183 + return nil, err
184 + }
185 +
186 + c, err := cid.Parse(out.Hash)
187 + if err != nil {
188 + return nil, err
189 + }
190 +
191 + return iface.IpfsPath(c), nil
192 +}
193 +
194 +func (api *ObjectAPI) AppendData(ctx context.Context, p iface.Path, r io.Reader) (iface.ResolvedPath, error) {
195 + var out objectOut
196 + err := api.core().request("object/patch/append-data", p.String()).
197 + FileBody(r).
198 + Exec(ctx, &out)
199 + if err != nil {
200 + return nil, err
201 + }
202 +
203 + c, err := cid.Parse(out.Hash)
204 + if err != nil {
205 + return nil, err
206 + }
207 +
208 + return iface.IpfsPath(c), nil
209 }
210
68 -func (api *ObjectAPI) AppendData(context.Context, iface.Path, io.Reader) (iface.ResolvedPath, error) {
69 - panic("implement me")
211 +func (api *ObjectAPI) SetData(ctx context.Context, p iface.Path, r io.Reader) (iface.ResolvedPath, error) {
212 + var out objectOut
213 + err := api.core().request("object/patch/set-data", p.String()).
214 + FileBody(r).
215 + Exec(ctx, &out)
216 + if err != nil {
217 + return nil, err
218 + }
219 +
220 + c, err := cid.Parse(out.Hash)
221 + if err != nil {
222 + return nil, err
223 + }
224 +
225 + return iface.IpfsPath(c), nil
226 }
227
72 -func (api *ObjectAPI) SetData(context.Context, iface.Path, io.Reader) (iface.ResolvedPath, error) {
73 - panic("implement me")
228 +type change struct {
229 + Type iface.ChangeType
230 + Path string
231 + Before cid.Cid
232 + After cid.Cid
233 }
234
76 -func (api *ObjectAPI) Diff(context.Context, iface.Path, iface.Path) ([]iface.ObjectChange, error) {
77 - panic("implement me")
235 +func (api *ObjectAPI) Diff(ctx context.Context, a iface.Path, b iface.Path) ([]iface.ObjectChange, error) {
236 + var out struct {
237 + Changes []change
238 + }
239 + if err := api.core().request("object/diff", a.String(), b.String()).Exec(ctx, &out); err != nil {
240 + return nil, err
241 + }
242 + res := make([]iface.ObjectChange, len(out.Changes))
243 + for i, ch := range out.Changes {
244 + res[i] = iface.ObjectChange{
245 + Type: ch.Type,
246 + Path: ch.Path,
247 + }
248 + if ch.Before != cid.Undef {
249 + res[i].Before = iface.IpfsPath(ch.Before)
250 + }
251 + if ch.After != cid.Undef {
252 + res[i].After = iface.IpfsPath(ch.After)
253 + }
254 + }
255 + return res, nil
256 }
257
258 func (api *ObjectAPI) core() *HttpApi {
client/httpapi/pin.go
+3 -3
@@ -83,8 +83,8 @@ func (api *PinAPI) Update(ctx context.Context, from iface.Path, to iface.Path, o
83 }
84
85 type pinVerifyRes struct {
86 - Cid string
87 - JOk bool `json:"Ok"`
86 + Cid string
87 + JOk bool `json:"Ok"`
88 JBadNodes []*badNode `json:"BadNodes,omitempty"`
89 }
90
@@ -101,7 +101,7 @@ func (r *pinVerifyRes) BadNodes() []iface.BadPinNode {
101 }
102
103 type badNode struct {
104 - Cid string
104 + Cid string
105 JErr string `json:"Err"`
106 }
107