core/commands!: remove deprecated object APIs (#10375)
Henrique Dias committed
Mar 22, 2024 at 09:32 UTC
9047fed8d5c3b6935c9a2358de2689451fcb7047
28 files changed
+163
-2033
assets/assets.go
+6
-18
@@ -9,9 +9,7 @@ import (
9
"github.com/ipfs/kubo/core/coreapi"
10
11
"github.com/ipfs/boxo/files"
12
- "github.com/ipfs/boxo/path"
12
cid "github.com/ipfs/go-cid"
14
- options "github.com/ipfs/kubo/core/coreiface/options"
13
)
14
15
//go:embed init-doc
@@ -39,12 +37,7 @@ func addAssetList(nd *core.IpfsNode, l []string) (cid.Cid, error) {
37
return cid.Cid{}, err
38
}
39
42
- dirb, err := api.Object().New(nd.Context(), options.Object.Type("unixfs-dir"))
43
- if err != nil {
44
- return cid.Cid{}, err
45
- }
46
-
47
- basePath := path.FromCid(dirb.Cid())
40
+ dirMap := map[string]files.Node{}
41
42
for _, p := range l {
43
d, err := Asset.ReadFile(p)
@@ -52,17 +45,12 @@ func addAssetList(nd *core.IpfsNode, l []string) (cid.Cid, error) {
45
return cid.Cid{}, fmt.Errorf("assets: could load Asset '%s': %s", p, err)
46
}
47
55
- fp, err := api.Unixfs().Add(nd.Context(), files.NewBytesFile(d))
56
- if err != nil {
57
- return cid.Cid{}, err
58
- }
59
-
60
- fname := gopath.Base(p)
48
+ dirMap[gopath.Base(p)] = files.NewBytesFile(d)
49
+ }
50
62
- basePath, err = api.Object().AddLink(nd.Context(), basePath, fname, fp)
63
- if err != nil {
64
- return cid.Cid{}, err
65
- }
51
+ basePath, err := api.Unixfs().Add(nd.Context(), files.NewMapDirectory(dirMap))
52
+ if err != nil {
53
+ return cid.Cid{}, err
54
}
55
56
if err := api.Pin().Add(nd.Context(), basePath); err != nil {
bin/ipns-republish
+1
-1
@@ -19,7 +19,7 @@ if [ $? -ne 0 ]; then
19
fi
20
21
# check the object is there
22
-ipfs object stat "$1" >/dev/null
22
+ipfs dag stat "$1" >/dev/null
23
if [ $? -ne 0 ]; then
24
echo "error: ipfs cannot find $1"
25
exit 1
client/rpc/object.go
-172
@@ -1,16 +1,10 @@
1
package rpc
2
3
import (
4
- "bytes"
4
"context"
6
- "fmt"
7
- "io"
5
9
- "github.com/ipfs/boxo/ipld/merkledag"
10
- ft "github.com/ipfs/boxo/ipld/unixfs"
6
"github.com/ipfs/boxo/path"
7
"github.com/ipfs/go-cid"
13
- ipld "github.com/ipfs/go-ipld-format"
8
iface "github.com/ipfs/kubo/core/coreiface"
9
caopts "github.com/ipfs/kubo/core/coreiface/options"
10
)
@@ -21,138 +15,6 @@ type objectOut struct {
15
Hash string
16
}
17
24
-func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (ipld.Node, error) {
25
- options, err := caopts.ObjectNewOptions(opts...)
26
- if err != nil {
27
- return nil, err
28
- }
29
-
30
- var n ipld.Node
31
- switch options.Type {
32
- case "empty":
33
- n = new(merkledag.ProtoNode)
34
- case "unixfs-dir":
35
- n = ft.EmptyDirNode()
36
- default:
37
- return nil, fmt.Errorf("unknown object type: %s", options.Type)
38
- }
39
-
40
- return n, nil
41
-}
42
-
43
-func (api *ObjectAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.ObjectPutOption) (path.ImmutablePath, error) {
44
- options, err := caopts.ObjectPutOptions(opts...)
45
- if err != nil {
46
- return path.ImmutablePath{}, 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 path.ImmutablePath{}, err
58
- }
59
-
60
- c, err := cid.Parse(out.Hash)
61
- if err != nil {
62
- return path.ImmutablePath{}, err
63
- }
64
-
65
- return path.FromCid(c), nil
66
-}
67
-
68
-func (api *ObjectAPI) Get(ctx context.Context, p path.Path) (ipld.Node, error) {
69
- r, err := api.core().Block().Get(ctx, p)
70
- if err != nil {
71
- return nil, err
72
- }
73
- b, err := io.ReadAll(r)
74
- if err != nil {
75
- return nil, err
76
- }
77
-
78
- return merkledag.DecodeProtobuf(b)
79
-}
80
-
81
-func (api *ObjectAPI) Data(ctx context.Context, p path.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
-
100
-func (api *ObjectAPI) Links(ctx context.Context, p path.Path) ([]*ipld.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([]*ipld.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] = &ipld.Link{
119
- Cid: c,
120
- Name: l.Name,
121
- Size: l.Size,
122
- }
123
- }
124
-
125
- return res, nil
126
-}
127
-
128
-func (api *ObjectAPI) Stat(ctx context.Context, p path.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
-
18
func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string, child path.Path, opts ...caopts.ObjectAddLinkOption) (path.ImmutablePath, error) {
19
options, err := caopts.ObjectAddLinkOptions(opts...)
20
if err != nil {
@@ -191,40 +53,6 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (
53
return path.FromCid(c), nil
54
}
55
194
-func (api *ObjectAPI) AppendData(ctx context.Context, p path.Path, r io.Reader) (path.ImmutablePath, 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 path.ImmutablePath{}, err
201
- }
202
-
203
- c, err := cid.Parse(out.Hash)
204
- if err != nil {
205
- return path.ImmutablePath{}, err
206
- }
207
-
208
- return path.FromCid(c), nil
209
-}
210
-
211
-func (api *ObjectAPI) SetData(ctx context.Context, p path.Path, r io.Reader) (path.ImmutablePath, 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 path.ImmutablePath{}, err
218
- }
219
-
220
- c, err := cid.Parse(out.Hash)
221
- if err != nil {
222
- return path.ImmutablePath{}, err
223
- }
224
-
225
- return path.FromCid(c), nil
226
-}
227
-
56
type change struct {
57
Type iface.ChangeType
58
Path string
core/commands/commands_test.go
+5
@@ -61,6 +61,11 @@ func TestCommands(t *testing.T) {
61
"/dag/stat",
62
"/dht",
63
"/dht/query",
64
+ "/dht/findprovs",
65
+ "/dht/findpeer",
66
+ "/dht/get",
67
+ "/dht/provide",
68
+ "/dht/put",
69
"/routing",
70
"/routing/put",
71
"/routing/get",
core/commands/dht.go
+17
-1
@@ -15,13 +15,19 @@ import (
15
var ErrNotDHT = errors.New("routing service is not a DHT")
16
17
var DhtCmd = &cmds.Command{
18
+ Status: cmds.Deprecated,
19
Helptext: cmds.HelpText{
20
Tagline: "Issue commands directly through the DHT.",
21
ShortDescription: ``,
22
},
23
24
Subcommands: map[string]*cmds.Command{
24
- "query": queryDhtCmd,
25
+ "query": queryDhtCmd,
26
+ "findprovs": RemovedDHTCmd,
27
+ "findpeer": RemovedDHTCmd,
28
+ "get": RemovedDHTCmd,
29
+ "put": RemovedDHTCmd,
30
+ "provide": RemovedDHTCmd,
31
},
32
}
33
@@ -32,6 +38,7 @@ type kademlia interface {
38
}
39
40
var queryDhtCmd = &cmds.Command{
41
+ Status: cmds.Deprecated,
42
Helptext: cmds.HelpText{
43
Tagline: "Find the closest Peer IDs to a given Peer ID by querying the DHT.",
44
ShortDescription: "Outputs a list of newline-delimited Peer IDs.",
@@ -114,3 +121,12 @@ var queryDhtCmd = &cmds.Command{
121
},
122
Type: routing.QueryEvent{},
123
}
124
+var RemovedDHTCmd = &cmds.Command{
125
+ Status: cmds.Removed,
126
+ Helptext: cmds.HelpText{
127
+ Tagline: "Removed, use 'ipfs routing' instead.",
128
+ },
129
+ Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
130
+ return errors.New("removed, use 'ipfs routing' instead")
131
+ },
132
+}
core/commands/object/object.go
+10
-530
@@ -1,28 +1,11 @@
1
package objectcmd
2
3
import (
4
- "encoding/base64"
4
"errors"
6
- "fmt"
7
- "io"
8
- "text/tabwriter"
5
6
cmds "github.com/ipfs/go-ipfs-cmds"
11
- "github.com/ipfs/kubo/core/commands/cmdenv"
12
- "github.com/ipfs/kubo/core/commands/cmdutils"
13
-
14
- humanize "github.com/dustin/go-humanize"
15
- dag "github.com/ipfs/boxo/ipld/merkledag"
16
- "github.com/ipfs/go-cid"
17
- ipld "github.com/ipfs/go-ipld-format"
18
- "github.com/ipfs/kubo/core/coreiface/options"
7
)
8
21
-type Node struct {
22
- Links []Link
23
- Data string
24
-}
25
-
9
type Link struct {
10
Name, Hash string
11
Size uint64
@@ -35,16 +18,6 @@ type Object struct {
18
19
var ErrDataEncoding = errors.New("unknown data field encoding")
20
38
-const (
39
- headersOptionName = "headers"
40
- encodingOptionName = "data-encoding"
41
- inputencOptionName = "inputenc"
42
- datafieldencOptionName = "datafieldenc"
43
- pinOptionName = "pin"
44
- quietOptionName = "quiet"
45
- humanOptionName = "human"
46
-)
47
-
21
var ObjectCmd = &cmds.Command{
22
Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
23
Helptext: cmds.HelpText{
@@ -55,516 +28,23 @@ directly. Deprecated, use more modern 'ipfs dag' and 'ipfs files' instead.`,
28
},
29
30
Subcommands: map[string]*cmds.Command{
58
- "data": ObjectDataCmd,
31
+ "data": RemovedObjectCmd,
32
"diff": ObjectDiffCmd,
60
- "get": ObjectGetCmd,
61
- "links": ObjectLinksCmd,
62
- "new": ObjectNewCmd,
33
+ "get": RemovedObjectCmd,
34
+ "links": RemovedObjectCmd,
35
+ "new": RemovedObjectCmd,
36
"patch": ObjectPatchCmd,
64
- "put": ObjectPutCmd,
65
- "stat": ObjectStatCmd,
66
- },
67
-}
68
-
69
-// ObjectDataCmd object data command
70
-var ObjectDataCmd = &cmds.Command{
71
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
72
- Helptext: cmds.HelpText{
73
- Tagline: "Deprecated way to read the raw bytes of a dag-pb object: use 'dag get' instead.",
74
- ShortDescription: `
75
-'ipfs object data' is a deprecated plumbing command for retrieving the raw
76
-bytes stored in a dag-pb node. It outputs to stdout, and <key> is a base58
77
-encoded multihash. Provided for legacy reasons. Use 'ipfs dag get' instead.
78
-`,
79
- LongDescription: `
80
-'ipfs object data' is a deprecated plumbing command for retrieving the raw
81
-bytes stored in a dag-pb node. It outputs to stdout, and <key> is a base58
82
-encoded multihash. Provided for legacy reasons. Use 'ipfs dag get' instead.
83
-
84
-Note that the "--encoding" option does not affect the output, since the output
85
-is the raw data of the object.
86
-`,
87
- },
88
-
89
- Arguments: []cmds.Argument{
90
- cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format.").EnableStdin(),
91
- },
92
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
93
- api, err := cmdenv.GetApi(env, req)
94
- if err != nil {
95
- return err
96
- }
97
-
98
- path, err := cmdutils.PathOrCidPath(req.Arguments[0])
99
- if err != nil {
100
- return err
101
- }
102
-
103
- data, err := api.Object().Data(req.Context, path)
104
- if err != nil {
105
- return err
106
- }
107
-
108
- return res.Emit(data)
109
- },
110
-}
111
-
112
-// ObjectLinksCmd object links command
113
-var ObjectLinksCmd = &cmds.Command{
114
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
115
- Helptext: cmds.HelpText{
116
- Tagline: "Deprecated way to output links in the specified dag-pb object: use 'dag get' instead.",
117
- ShortDescription: `
118
-'ipfs object links' is a plumbing command for retrieving the links from
119
-a dag-pb node. It outputs to stdout, and <key> is a base58 encoded
120
-multihash. Provided for legacy reasons. Use 'ipfs dag get' instead.
121
-`,
122
- },
123
-
124
- Arguments: []cmds.Argument{
125
- cmds.StringArg("key", true, false, "Key of the dag-pb object to retrieve, in base58-encoded multihash format.").EnableStdin(),
126
- },
127
- Options: []cmds.Option{
128
- cmds.BoolOption(headersOptionName, "v", "Print table headers (Hash, Size, Name)."),
129
- },
130
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
131
- api, err := cmdenv.GetApi(env, req)
132
- if err != nil {
133
- return err
134
- }
135
-
136
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
137
- if err != nil {
138
- return err
139
- }
140
-
141
- path, err := cmdutils.PathOrCidPath(req.Arguments[0])
142
- if err != nil {
143
- return err
144
- }
145
-
146
- rp, _, err := api.ResolvePath(req.Context, path)
147
- if err != nil {
148
- return err
149
- }
150
-
151
- links, err := api.Object().Links(req.Context, rp)
152
- if err != nil {
153
- return err
154
- }
155
-
156
- outLinks := make([]Link, len(links))
157
- for i, link := range links {
158
- outLinks[i] = Link{
159
- Hash: enc.Encode(link.Cid),
160
- Name: link.Name,
161
- Size: link.Size,
162
- }
163
- }
164
-
165
- out := &Object{
166
- Hash: enc.Encode(rp.RootCid()),
167
- Links: outLinks,
168
- }
169
-
170
- return cmds.EmitOnce(res, out)
171
- },
172
- Encoders: cmds.EncoderMap{
173
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {
174
- tw := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0)
175
- headers, _ := req.Options[headersOptionName].(bool)
176
- if headers {
177
- fmt.Fprintln(tw, "Hash\tSize\tName")
178
- }
179
- for _, link := range out.Links {
180
- fmt.Fprintf(tw, "%s\t%v\t%s\n", link.Hash, link.Size, cmdenv.EscNonPrint(link.Name))
181
- }
182
- tw.Flush()
183
-
184
- return nil
185
- }),
186
- },
187
- Type: &Object{},
188
-}
189
-
190
-// ObjectGetCmd object get command
191
-var ObjectGetCmd = &cmds.Command{
192
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
193
- Helptext: cmds.HelpText{
194
- Tagline: "Deprecated way to get and serialize the dag-pb node. Use 'dag get' instead",
195
- ShortDescription: `
196
-'ipfs object get' is a plumbing command for retrieving dag-pb nodes.
197
-It serializes the DAG node to the format specified by the "--encoding"
198
-flag. It outputs to stdout, and <key> is a base58 encoded multihash.
199
-
200
-DEPRECATED and provided for legacy reasons. Use 'ipfs dag get' instead.
201
-`,
202
- },
203
-
204
- Arguments: []cmds.Argument{
205
- cmds.StringArg("key", true, false, "Key of the dag-pb object to retrieve, in base58-encoded multihash format.").EnableStdin(),
206
- },
207
- Options: []cmds.Option{
208
- cmds.StringOption(encodingOptionName, "Encoding type of the data field, either \"text\" or \"base64\".").WithDefault("text"),
209
- },
210
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
211
- api, err := cmdenv.GetApi(env, req)
212
- if err != nil {
213
- return err
214
- }
215
-
216
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
217
- if err != nil {
218
- return err
219
- }
220
-
221
- path, err := cmdutils.PathOrCidPath(req.Arguments[0])
222
- if err != nil {
223
- return err
224
- }
225
-
226
- datafieldenc, _ := req.Options[encodingOptionName].(string)
227
- if err != nil {
228
- return err
229
- }
230
-
231
- nd, err := api.Object().Get(req.Context, path)
232
- if err != nil {
233
- return err
234
- }
235
-
236
- r, err := api.Object().Data(req.Context, path)
237
- if err != nil {
238
- return err
239
- }
240
-
241
- data, err := io.ReadAll(r)
242
- if err != nil {
243
- return err
244
- }
245
-
246
- out, err := encodeData(data, datafieldenc)
247
- if err != nil {
248
- return err
249
- }
250
-
251
- node := &Node{
252
- Links: make([]Link, len(nd.Links())),
253
- Data: out,
254
- }
255
-
256
- for i, link := range nd.Links() {
257
- node.Links[i] = Link{
258
- Hash: enc.Encode(link.Cid),
259
- Name: link.Name,
260
- Size: link.Size,
261
- }
262
- }
263
-
264
- return cmds.EmitOnce(res, node)
265
- },
266
- Type: Node{},
267
- Encoders: cmds.EncoderMap{
268
- cmds.Protobuf: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Node) error {
269
- // deserialize the Data field as text as this was the standard behaviour
270
- object, err := deserializeNode(out, "text")
271
- if err != nil {
272
- return nil
273
- }
274
-
275
- marshaled, err := object.Marshal()
276
- if err != nil {
277
- return err
278
- }
279
- _, err = w.Write(marshaled)
280
- return err
281
- }),
282
- },
283
-}
284
-
285
-// ObjectStatCmd object stat command
286
-var ObjectStatCmd = &cmds.Command{
287
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
288
- Helptext: cmds.HelpText{
289
- Tagline: "Deprecated way to read stats for the dag-pb node. Use 'files stat' instead.",
290
- ShortDescription: `
291
-'ipfs object stat' is a plumbing command to print dag-pb node statistics.
292
-<key> is a base58 encoded multihash.
293
-
294
-DEPRECATED: modern replacements are 'files stat' and 'dag stat'
295
-`,
296
- LongDescription: `
297
-'ipfs object stat' is a plumbing command to print dag-pb node statistics.
298
-<key> is a base58 encoded multihash. It outputs to stdout:
299
-
300
- NumLinks int number of links in link table
301
- BlockSize int size of the raw, encoded data
302
- LinksSize int size of the links segment
303
- DataSize int size of the data segment
304
- CumulativeSize int cumulative size of object and its references
305
-
306
-DEPRECATED: Provided for legacy reasons. Modern replacements:
307
-
308
- For unixfs, 'ipfs files stat' can be used:
309
-
310
- $ ipfs files stat --with-local /ipfs/QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX
311
- QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX
312
- Size: 5
313
- CumulativeSize: 13
314
- ChildBlocks: 0
315
- Type: file
316
- Local: 13 B of 13 B (100.00%)
317
-
318
- Reported sizes are based on metadata present in root block, and should not be
319
- trusted. A slower, but more secure alternative is 'ipfs dag stat', which
320
- will work for every DAG type. It comes with a benefit of calculating the
321
- size by walking the DAG:
322
-
323
- $ ipfs dag stat /ipfs/QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX
324
- Size: 13, NumBlocks: 1
325
-`,
326
- },
327
-
328
- Arguments: []cmds.Argument{
329
- cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format.").EnableStdin(),
330
- },
331
- Options: []cmds.Option{
332
- cmds.BoolOption(humanOptionName, "Print sizes in human readable format (e.g., 1K 234M 2G)"),
333
- },
334
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
335
- api, err := cmdenv.GetApi(env, req)
336
- if err != nil {
337
- return err
338
- }
339
-
340
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
341
- if err != nil {
342
- return err
343
- }
344
-
345
- p, err := cmdutils.PathOrCidPath(req.Arguments[0])
346
- if err != nil {
347
- return err
348
- }
349
-
350
- ns, err := api.Object().Stat(req.Context, p)
351
- if err != nil {
352
- return err
353
- }
354
-
355
- oldStat := &ipld.NodeStat{
356
- Hash: enc.Encode(ns.Cid),
357
- NumLinks: ns.NumLinks,
358
- BlockSize: ns.BlockSize,
359
- LinksSize: ns.LinksSize,
360
- DataSize: ns.DataSize,
361
- CumulativeSize: ns.CumulativeSize,
362
- }
363
-
364
- return cmds.EmitOnce(res, oldStat)
365
- },
366
- Type: ipld.NodeStat{},
367
- Encoders: cmds.EncoderMap{
368
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *ipld.NodeStat) error {
369
- wtr := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
370
- defer wtr.Flush()
371
- fw := func(s string, n int) {
372
- fmt.Fprintf(wtr, "%s:\t%d\n", s, n)
373
- }
374
- human, _ := req.Options[humanOptionName].(bool)
375
- fw("NumLinks", out.NumLinks)
376
- fw("BlockSize", out.BlockSize)
377
- fw("LinksSize", out.LinksSize)
378
- fw("DataSize", out.DataSize)
379
- if human {
380
- fmt.Fprintf(wtr, "%s:\t%s\n", "CumulativeSize", humanize.Bytes(uint64(out.CumulativeSize)))
381
- } else {
382
- fw("CumulativeSize", out.CumulativeSize)
383
- }
384
-
385
- return nil
386
- }),
387
- },
388
-}
389
-
390
-// ObjectPutCmd object put command
391
-var ObjectPutCmd = &cmds.Command{
392
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
393
- Helptext: cmds.HelpText{
394
- Tagline: "Deprecated way to store input as a DAG object. Use 'dag put' instead.",
395
- ShortDescription: `
396
-'ipfs object put' is a plumbing command for storing dag-pb nodes.
397
-It reads from stdin, and the output is a base58 encoded multihash.
398
-
399
-DEPRECATED and provided for legacy reasons. Use 'ipfs dag put' instead.
400
-`,
401
- },
402
-
403
- Arguments: []cmds.Argument{
404
- cmds.FileArg("data", true, false, "Data to be stored as a dag-pb object.").EnableStdin(),
405
- },
406
- Options: []cmds.Option{
407
- cmds.StringOption(inputencOptionName, "Encoding type of input data. One of: {\"protobuf\", \"json\"}.").WithDefault("json"),
408
- cmds.StringOption(datafieldencOptionName, "Encoding type of the data field, either \"text\" or \"base64\".").WithDefault("text"),
409
- cmds.BoolOption(pinOptionName, "Pin this object when adding."),
410
- cmds.BoolOption(quietOptionName, "q", "Write minimal output."),
411
- },
412
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
413
- api, err := cmdenv.GetApi(env, req)
414
- if err != nil {
415
- return err
416
- }
417
-
418
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
419
- if err != nil {
420
- return err
421
- }
422
-
423
- file, err := cmdenv.GetFileArg(req.Files.Entries())
424
- if err != nil {
425
- return err
426
- }
427
-
428
- inputenc, _ := req.Options[inputencOptionName].(string)
429
- if err != nil {
430
- return err
431
- }
432
-
433
- datafieldenc, _ := req.Options[datafieldencOptionName].(string)
434
- if err != nil {
435
- return err
436
- }
437
-
438
- dopin, _ := req.Options[pinOptionName].(bool)
439
- if err != nil {
440
- return err
441
- }
442
-
443
- p, err := api.Object().Put(req.Context, file,
444
- options.Object.DataType(datafieldenc),
445
- options.Object.InputEnc(inputenc),
446
- options.Object.Pin(dopin))
447
- if err != nil {
448
- return err
449
- }
450
-
451
- return cmds.EmitOnce(res, &Object{Hash: enc.Encode(p.RootCid())})
452
- },
453
- Encoders: cmds.EncoderMap{
454
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {
455
- quiet, _ := req.Options[quietOptionName].(bool)
456
-
457
- o := out.Hash
458
- if !quiet {
459
- o = "added " + o
460
- }
461
-
462
- fmt.Fprintln(w, o)
463
-
464
- return nil
465
- }),
37
+ "put": RemovedObjectCmd,
38
+ "stat": RemovedObjectCmd,
39
},
467
- Type: Object{},
40
}
41
470
-// ObjectNewCmd object new command
471
-var ObjectNewCmd = &cmds.Command{
472
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
42
+var RemovedObjectCmd = &cmds.Command{
43
+ Status: cmds.Removed,
44
Helptext: cmds.HelpText{
474
- Tagline: "Deprecated way to create a new dag-pb object from a template.",
475
- ShortDescription: `
476
-'ipfs object new' is a plumbing command for creating new dag-pb nodes.
477
-DEPRECATED and provided for legacy reasons. Use 'dag put' and 'files' instead.
478
-`,
479
- LongDescription: `
480
-'ipfs object new' is a plumbing command for creating new dag-pb nodes.
481
-By default it creates and returns a new empty merkledag node, but
482
-you may pass an optional template argument to create a preformatted
483
-node.
484
-
485
-Available templates:
486
- * unixfs-dir
487
-
488
-DEPRECATED and provided for legacy reasons. Use 'dag put' and 'files' instead.
489
-`,
490
- },
491
- Arguments: []cmds.Argument{
492
- cmds.StringArg("template", false, false, "Template to use. Optional."),
45
+ Tagline: "Removed, use 'ipfs dag' or 'ipfs files' instead.",
46
},
47
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
495
- api, err := cmdenv.GetApi(env, req)
496
- if err != nil {
497
- return err
498
- }
499
-
500
- enc, err := cmdenv.GetLowLevelCidEncoder(req)
501
- if err != nil {
502
- return err
503
- }
504
-
505
- template := "empty"
506
- if len(req.Arguments) == 1 {
507
- template = req.Arguments[0]
508
- }
509
-
510
- nd, err := api.Object().New(req.Context, options.Object.Type(template))
511
- if err != nil && err != io.EOF {
512
- return err
513
- }
514
-
515
- return cmds.EmitOnce(res, &Object{Hash: enc.Encode(nd.Cid())})
48
+ return errors.New("removed, use 'ipfs dag' or 'ipfs files' instead")
49
},
517
- Encoders: cmds.EncoderMap{
518
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {
519
- fmt.Fprintln(w, out.Hash)
520
- return nil
521
- }),
522
- },
523
- Type: Object{},
524
-}
525
-
526
-// converts the Node object into a real dag.ProtoNode
527
-func deserializeNode(nd *Node, dataFieldEncoding string) (*dag.ProtoNode, error) {
528
- dagnode := new(dag.ProtoNode)
529
- switch dataFieldEncoding {
530
- case "text":
531
- dagnode.SetData([]byte(nd.Data))
532
- case "base64":
533
- data, err := base64.StdEncoding.DecodeString(nd.Data)
534
- if err != nil {
535
- return nil, err
536
- }
537
- dagnode.SetData(data)
538
- default:
539
- return nil, ErrDataEncoding
540
- }
541
-
542
- links := make([]*ipld.Link, len(nd.Links))
543
- for i, link := range nd.Links {
544
- c, err := cid.Decode(link.Hash)
545
- if err != nil {
546
- return nil, err
547
- }
548
- links[i] = &ipld.Link{
549
- Name: link.Name,
550
- Size: link.Size,
551
- Cid: c,
552
- }
553
- }
554
- if err := dagnode.SetLinks(links); err != nil {
555
- return nil, err
556
- }
557
-
558
- return dagnode, nil
559
-}
560
-
561
-func encodeData(data []byte, encoding string) (string, error) {
562
- switch encoding {
563
- case "text":
564
- return string(data), nil
565
- case "base64":
566
- return base64.StdEncoding.EncodeToString(data), nil
567
- }
568
-
569
- return "", ErrDataEncoding
50
}
core/commands/object/patch.go
+2
-114
@@ -37,128 +37,16 @@ For modern use cases, use MFS with 'files' commands: 'ipfs files --help'.
37
},
38
Arguments: []cmds.Argument{},
39
Subcommands: map[string]*cmds.Command{
40
- "append-data": patchAppendDataCmd,
40
+ "append-data": RemovedObjectCmd,
41
"add-link": patchAddLinkCmd,
42
"rm-link": patchRmLinkCmd,
43
- "set-data": patchSetDataCmd,
43
+ "set-data": RemovedObjectCmd,
44
},
45
Options: []cmds.Option{
46
cmdutils.AllowBigBlockOption,
47
},
48
}
49
50
-var patchAppendDataCmd = &cmds.Command{
51
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
52
- Helptext: cmds.HelpText{
53
- Tagline: "Deprecated way to append data to the data segment of a DAG node.",
54
- ShortDescription: `
55
-Append data to what already exists in the data segment in the given object.
56
-
57
-Example:
58
-
59
- $ echo "hello" | ipfs object patch $HASH append-data
60
-
61
-NOTE: This does not append data to a file - it modifies the actual raw
62
-data within a dag-pb object. Blocks have a max size of 1MiB and objects larger than
63
-the limit will not be respected by the network.
64
-
65
-DEPRECATED and provided for legacy reasons. Use 'ipfs add' or 'ipfs files' instead.
66
-`,
67
- },
68
- Arguments: []cmds.Argument{
69
- cmds.StringArg("root", true, false, "The hash of the node to modify."),
70
- cmds.FileArg("data", true, false, "Data to append.").EnableStdin(),
71
- },
72
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
73
- api, err := cmdenv.GetApi(env, req)
74
- if err != nil {
75
- return err
76
- }
77
-
78
- root, err := cmdutils.PathOrCidPath(req.Arguments[0])
79
- if err != nil {
80
- return err
81
- }
82
-
83
- file, err := cmdenv.GetFileArg(req.Files.Entries())
84
- if err != nil {
85
- return err
86
- }
87
-
88
- p, err := api.Object().AppendData(req.Context, root, file)
89
- if err != nil {
90
- return err
91
- }
92
-
93
- if err := cmdutils.CheckCIDSize(req, p.RootCid(), api.Dag()); err != nil {
94
- return err
95
- }
96
-
97
- return cmds.EmitOnce(res, &Object{Hash: p.RootCid().String()})
98
- },
99
- Type: &Object{},
100
- Encoders: cmds.EncoderMap{
101
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, obj *Object) error {
102
- _, err := fmt.Fprintln(w, obj.Hash)
103
- return err
104
- }),
105
- },
106
-}
107
-
108
-var patchSetDataCmd = &cmds.Command{
109
- Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
110
- Helptext: cmds.HelpText{
111
- Tagline: "Deprecated way to set the data field of dag-pb object.",
112
- ShortDescription: `
113
-Set the data of an IPFS object from stdin or with the contents of a file.
114
-
115
-Example:
116
-
117
- $ echo "my data" | ipfs object patch $MYHASH set-data
118
-
119
-DEPRECATED and provided for legacy reasons. Use 'files cp' and 'dag put' instead.
120
-`,
121
- },
122
- Arguments: []cmds.Argument{
123
- cmds.StringArg("root", true, false, "The hash of the node to modify."),
124
- cmds.FileArg("data", true, false, "The data to set the object to.").EnableStdin(),
125
- },
126
- Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
127
- api, err := cmdenv.GetApi(env, req)
128
- if err != nil {
129
- return err
130
- }
131
-
132
- root, err := cmdutils.PathOrCidPath(req.Arguments[0])
133
- if err != nil {
134
- return err
135
- }
136
-
137
- file, err := cmdenv.GetFileArg(req.Files.Entries())
138
- if err != nil {
139
- return err
140
- }
141
-
142
- p, err := api.Object().SetData(req.Context, root, file)
143
- if err != nil {
144
- return err
145
- }
146
-
147
- if err := cmdutils.CheckCIDSize(req, p.RootCid(), api.Dag()); err != nil {
148
- return err
149
- }
150
-
151
- return cmds.EmitOnce(res, &Object{Hash: p.RootCid().String()})
152
- },
153
- Type: Object{},
154
- Encoders: cmds.EncoderMap{
155
- cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {
156
- fmt.Fprintln(w, out.Hash)
157
- return nil
158
- }),
159
- },
160
-}
161
-
50
var patchRmLinkCmd = &cmds.Command{
51
Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
52
Helptext: cmds.HelpText{
core/coreapi/object.go
-263
@@ -1,22 +1,12 @@
1
package coreapi
2
3
import (
4
- "bytes"
4
"context"
6
- "encoding/base64"
7
- "encoding/json"
8
- "encoding/xml"
9
- "errors"
10
- "fmt"
11
- "io"
5
6
dag "github.com/ipfs/boxo/ipld/merkledag"
7
"github.com/ipfs/boxo/ipld/merkledag/dagutils"
8
ft "github.com/ipfs/boxo/ipld/unixfs"
9
"github.com/ipfs/boxo/path"
17
- pin "github.com/ipfs/boxo/pinning/pinner"
18
- cid "github.com/ipfs/go-cid"
19
- ipld "github.com/ipfs/go-ipld-format"
10
coreiface "github.com/ipfs/kubo/core/coreiface"
11
caopts "github.com/ipfs/kubo/core/coreiface/options"
12
"go.opentelemetry.io/otel/attribute"
@@ -25,8 +15,6 @@ import (
15
"github.com/ipfs/kubo/tracing"
16
)
17
28
-const inputLimit = 2 << 20
29
-
18
type ObjectAPI CoreAPI
19
20
type Link struct {
@@ -39,180 +27,6 @@ type Node struct {
27
Data string
28
}
29
42
-func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (ipld.Node, error) {
43
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "New")
44
- defer span.End()
45
-
46
- options, err := caopts.ObjectNewOptions(opts...)
47
- if err != nil {
48
- return nil, err
49
- }
50
-
51
- var n ipld.Node
52
- switch options.Type {
53
- case "empty":
54
- n = new(dag.ProtoNode)
55
- case "unixfs-dir":
56
- n = ft.EmptyDirNode()
57
- default:
58
- return nil, fmt.Errorf("unknown node type: %s", options.Type)
59
- }
60
-
61
- err = api.dag.Add(ctx, n)
62
- if err != nil {
63
- return nil, err
64
- }
65
- return n, nil
66
-}
67
-
68
-func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.ObjectPutOption) (path.ImmutablePath, error) {
69
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Put")
70
- defer span.End()
71
-
72
- options, err := caopts.ObjectPutOptions(opts...)
73
- if err != nil {
74
- return path.ImmutablePath{}, err
75
- }
76
- span.SetAttributes(
77
- attribute.Bool("pin", options.Pin),
78
- attribute.String("datatype", options.DataType),
79
- attribute.String("inputenc", options.InputEnc),
80
- )
81
-
82
- data, err := io.ReadAll(io.LimitReader(src, inputLimit+10))
83
- if err != nil {
84
- return path.ImmutablePath{}, err
85
- }
86
-
87
- var dagnode *dag.ProtoNode
88
- switch options.InputEnc {
89
- case "json":
90
- node := new(Node)
91
- decoder := json.NewDecoder(bytes.NewReader(data))
92
- decoder.DisallowUnknownFields()
93
- err = decoder.Decode(node)
94
- if err != nil {
95
- return path.ImmutablePath{}, err
96
- }
97
-
98
- dagnode, err = deserializeNode(node, options.DataType)
99
- if err != nil {
100
- return path.ImmutablePath{}, err
101
- }
102
-
103
- case "protobuf":
104
- dagnode, err = dag.DecodeProtobuf(data)
105
-
106
- case "xml":
107
- node := new(Node)
108
- err = xml.Unmarshal(data, node)
109
- if err != nil {
110
- return path.ImmutablePath{}, err
111
- }
112
-
113
- dagnode, err = deserializeNode(node, options.DataType)
114
- if err != nil {
115
- return path.ImmutablePath{}, err
116
- }
117
-
118
- default:
119
- return path.ImmutablePath{}, errors.New("unknown object encoding")
120
- }
121
-
122
- if err != nil {
123
- return path.ImmutablePath{}, err
124
- }
125
-
126
- if options.Pin {
127
- defer api.blockstore.PinLock(ctx).Unlock(ctx)
128
- }
129
-
130
- err = api.dag.Add(ctx, dagnode)
131
- if err != nil {
132
- return path.ImmutablePath{}, err
133
- }
134
-
135
- if options.Pin {
136
- if err := api.pinning.PinWithMode(ctx, dagnode.Cid(), pin.Recursive, ""); err != nil {
137
- return path.ImmutablePath{}, err
138
- }
139
-
140
- err = api.pinning.Flush(ctx)
141
- if err != nil {
142
- return path.ImmutablePath{}, err
143
- }
144
- }
145
-
146
- return path.FromCid(dagnode.Cid()), nil
147
-}
148
-
149
-func (api *ObjectAPI) Get(ctx context.Context, path path.Path) (ipld.Node, error) {
150
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Get", trace.WithAttributes(attribute.String("path", path.String())))
151
- defer span.End()
152
- return api.core().ResolveNode(ctx, path)
153
-}
154
-
155
-func (api *ObjectAPI) Data(ctx context.Context, path path.Path) (io.Reader, error) {
156
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Data", trace.WithAttributes(attribute.String("path", path.String())))
157
- defer span.End()
158
-
159
- nd, err := api.core().ResolveNode(ctx, path)
160
- if err != nil {
161
- return nil, err
162
- }
163
-
164
- pbnd, ok := nd.(*dag.ProtoNode)
165
- if !ok {
166
- return nil, dag.ErrNotProtobuf
167
- }
168
-
169
- return bytes.NewReader(pbnd.Data()), nil
170
-}
171
-
172
-func (api *ObjectAPI) Links(ctx context.Context, path path.Path) ([]*ipld.Link, error) {
173
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Links", trace.WithAttributes(attribute.String("path", path.String())))
174
- defer span.End()
175
-
176
- nd, err := api.core().ResolveNode(ctx, path)
177
- if err != nil {
178
- return nil, err
179
- }
180
-
181
- links := nd.Links()
182
- out := make([]*ipld.Link, len(links))
183
- for n, l := range links {
184
- out[n] = (*ipld.Link)(l)
185
- }
186
-
187
- return out, nil
188
-}
189
-
190
-func (api *ObjectAPI) Stat(ctx context.Context, path path.Path) (*coreiface.ObjectStat, error) {
191
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Stat", trace.WithAttributes(attribute.String("path", path.String())))
192
- defer span.End()
193
-
194
- nd, err := api.core().ResolveNode(ctx, path)
195
- if err != nil {
196
- return nil, err
197
- }
198
-
199
- stat, err := nd.Stat()
200
- if err != nil {
201
- return nil, err
202
- }
203
-
204
- out := &coreiface.ObjectStat{
205
- Cid: nd.Cid(),
206
- NumLinks: stat.NumLinks,
207
- BlockSize: stat.BlockSize,
208
- LinksSize: stat.LinksSize,
209
- DataSize: stat.DataSize,
210
- CumulativeSize: stat.CumulativeSize,
211
- }
212
-
213
- return out, nil
214
-}
215
-
30
func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string, child path.Path, opts ...caopts.ObjectAddLinkOption) (path.ImmutablePath, error) {
31
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "AddLink", trace.WithAttributes(
32
attribute.String("base", base.String()),
@@ -294,49 +108,6 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (
108
return path.FromCid(nnode.Cid()), nil
109
}
110
297
-func (api *ObjectAPI) AppendData(ctx context.Context, path path.Path, r io.Reader) (path.ImmutablePath, error) {
298
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "AppendData", trace.WithAttributes(attribute.String("path", path.String())))
299
- defer span.End()
300
-
301
- return api.patchData(ctx, path, r, true)
302
-}
303
-
304
-func (api *ObjectAPI) SetData(ctx context.Context, path path.Path, r io.Reader) (path.ImmutablePath, error) {
305
- ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "SetData", trace.WithAttributes(attribute.String("path", path.String())))
306
- defer span.End()
307
-
308
- return api.patchData(ctx, path, r, false)
309
-}
310
-
311
-func (api *ObjectAPI) patchData(ctx context.Context, p path.Path, r io.Reader, appendData bool) (path.ImmutablePath, error) {
312
- nd, err := api.core().ResolveNode(ctx, p)
313
- if err != nil {
314
- return path.ImmutablePath{}, err
315
- }
316
-
317
- pbnd, ok := nd.(*dag.ProtoNode)
318
- if !ok {
319
- return path.ImmutablePath{}, dag.ErrNotProtobuf
320
- }
321
-
322
- data, err := io.ReadAll(r)
323
- if err != nil {
324
- return path.ImmutablePath{}, err
325
- }
326
-
327
- if appendData {
328
- data = append(pbnd.Data(), data...)
329
- }
330
- pbnd.SetData(data)
331
-
332
- err = api.dag.Add(ctx, pbnd)
333
- if err != nil {
334
- return path.ImmutablePath{}, err
335
- }
336
-
337
- return path.FromCid(pbnd.Cid()), nil
338
-}
339
-
111
func (api *ObjectAPI) Diff(ctx context.Context, before path.Path, after path.Path) ([]coreiface.ObjectChange, error) {
112
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Diff", trace.WithAttributes(
113
attribute.String("before", before.String()),
@@ -381,37 +152,3 @@ func (api *ObjectAPI) Diff(ctx context.Context, before path.Path, after path.Pat
152
func (api *ObjectAPI) core() coreiface.CoreAPI {
153
return (*CoreAPI)(api)
154
}
384
-
385
-func deserializeNode(nd *Node, dataFieldEncoding string) (*dag.ProtoNode, error) {
386
- dagnode := new(dag.ProtoNode)
387
- switch dataFieldEncoding {
388
- case "text":
389
- dagnode.SetData([]byte(nd.Data))
390
- case "base64":
391
- data, err := base64.StdEncoding.DecodeString(nd.Data)
392
- if err != nil {
393
- return nil, err
394
- }
395
- dagnode.SetData(data)
396
- default:
397
- return nil, fmt.Errorf("unknown data field encoding")
398
- }
399
-
400
- links := make([]*ipld.Link, len(nd.Links))
401
- for i, link := range nd.Links {
402
- c, err := cid.Decode(link.Hash)
403
- if err != nil {
404
- return nil, err
405
- }
406
- links[i] = &ipld.Link{
407
- Name: link.Name,
408
- Size: link.Size,
409
- Cid: c,
410
- }
411
- }
412
- if err := dagnode.SetLinks(links); err != nil {
413
- return nil, err
414
- }
415
-
416
- return dagnode, nil
417
-}
core/coreiface/object.go
-49
@@ -2,36 +2,11 @@ package iface
2
3
import (
4
"context"
5
- "io"
5
6
"github.com/ipfs/boxo/path"
7
"github.com/ipfs/kubo/core/coreiface/options"
9
-
10
- "github.com/ipfs/go-cid"
11
- ipld "github.com/ipfs/go-ipld-format"
8
)
9
14
-// ObjectStat provides information about dag nodes
15
-type ObjectStat struct {
16
- // Cid is the CID of the node
17
- Cid cid.Cid
18
-
19
- // NumLinks is number of links the node contains
20
- NumLinks int
21
-
22
- // BlockSize is size of the raw serialized node
23
- BlockSize int
24
-
25
- // LinksSize is size of the links block section
26
- LinksSize int
27
-
28
- // DataSize is the size of data block section
29
- DataSize int
30
-
31
- // CumulativeSize is size of the tree (BlockSize + link sizes)
32
- CumulativeSize int
33
-}
34
-
10
// ChangeType denotes type of change in ObjectChange
11
type ChangeType int
12
@@ -69,24 +44,6 @@ type ObjectChange struct {
44
// ObjectAPI specifies the interface to MerkleDAG and contains useful utilities
45
// for manipulating MerkleDAG data structures.
46
type ObjectAPI interface {
72
- // New creates new, empty (by default) dag-node.
73
- New(context.Context, ...options.ObjectNewOption) (ipld.Node, error)
74
-
75
- // Put imports the data into merkledag
76
- Put(context.Context, io.Reader, ...options.ObjectPutOption) (path.ImmutablePath, error)
77
-
78
- // Get returns the node for the path
79
- Get(context.Context, path.Path) (ipld.Node, error)
80
-
81
- // Data returns reader for data of the node
82
- Data(context.Context, path.Path) (io.Reader, error)
83
-
84
- // Links returns lint or links the node contains
85
- Links(context.Context, path.Path) ([]*ipld.Link, error)
86
-
87
- // Stat returns information about the node
88
- Stat(context.Context, path.Path) (*ObjectStat, error)
89
-
47
// AddLink adds a link under the specified path. child path can point to a
48
// subdirectory within the patent which must be present (can be overridden
49
// with WithCreate option).
@@ -95,12 +52,6 @@ type ObjectAPI interface {
52
// RmLink removes a link from the node
53
RmLink(ctx context.Context, base path.Path, link string) (path.ImmutablePath, error)
54
98
- // AppendData appends data to the node
99
- AppendData(context.Context, path.Path, io.Reader) (path.ImmutablePath, error)
100
-
101
- // SetData sets the data contained in the node
102
- SetData(context.Context, path.Path, io.Reader) (path.ImmutablePath, error)
103
-
55
// Diff returns a set of changes needed to transform the first object into the
56
// second.
57
Diff(context.Context, path.Path, path.Path) ([]ObjectChange, error)
core/coreiface/options/object.go
-90
@@ -1,55 +1,13 @@
1
package options
2
3
-type ObjectNewSettings struct {
4
- Type string
5
-}
6
-
7
-type ObjectPutSettings struct {
8
- InputEnc string
9
- DataType string
10
- Pin bool
11
-}
12
-
3
type ObjectAddLinkSettings struct {
4
Create bool
5
}
6
7
type (
18
- ObjectNewOption func(*ObjectNewSettings) error
19
- ObjectPutOption func(*ObjectPutSettings) error
8
ObjectAddLinkOption func(*ObjectAddLinkSettings) error
9
)
10
23
-func ObjectNewOptions(opts ...ObjectNewOption) (*ObjectNewSettings, error) {
24
- options := &ObjectNewSettings{
25
- Type: "empty",
26
- }
27
-
28
- for _, opt := range opts {
29
- err := opt(options)
30
- if err != nil {
31
- return nil, err
32
- }
33
- }
34
- return options, nil
35
-}
36
-
37
-func ObjectPutOptions(opts ...ObjectPutOption) (*ObjectPutSettings, error) {
38
- options := &ObjectPutSettings{
39
- InputEnc: "json",
40
- DataType: "text",
41
- Pin: false,
42
- }
43
-
44
- for _, opt := range opts {
45
- err := opt(options)
46
- if err != nil {
47
- return nil, err
48
- }
49
- }
50
- return options, nil
51
-}
52
-
11
func ObjectAddLinkOptions(opts ...ObjectAddLinkOption) (*ObjectAddLinkSettings, error) {
12
options := &ObjectAddLinkSettings{
13
Create: false,
@@ -68,54 +26,6 @@ type objectOpts struct{}
26
27
var Object objectOpts
28
71
-// Type is an option for Object.New which allows to change the type of created
72
-// dag node.
73
-//
74
-// Supported types:
75
-// * 'empty' - Empty node
76
-// * 'unixfs-dir' - Empty UnixFS directory
77
-func (objectOpts) Type(t string) ObjectNewOption {
78
- return func(settings *ObjectNewSettings) error {
79
- settings.Type = t
80
- return nil
81
- }
82
-}
83
-
84
-// InputEnc is an option for Object.Put which specifies the input encoding of the
85
-// data. Default is "json".
86
-//
87
-// Supported encodings:
88
-// * "protobuf"
89
-// * "json"
90
-func (objectOpts) InputEnc(e string) ObjectPutOption {
91
- return func(settings *ObjectPutSettings) error {
92
- settings.InputEnc = e
93
- return nil
94
- }
95
-}
96
-
97
-// DataType is an option for Object.Put which specifies the encoding of data
98
-// field when using Json or XML input encoding.
99
-//
100
-// Supported types:
101
-// * "text" (default)
102
-// * "base64"
103
-func (objectOpts) DataType(t string) ObjectPutOption {
104
- return func(settings *ObjectPutSettings) error {
105
- settings.DataType = t
106
- return nil
107
- }
108
-}
109
-
110
-// Pin is an option for Object.Put which specifies whether to pin the added
111
-// objects, default is false
112
-func (objectOpts) Pin(pin bool) ObjectPutOption {
113
- return func(settings *ObjectPutSettings) error {
114
- settings.Pin = pin
115
- return nil
116
- }
117
-}
118
-
29
// Create is an option for Object.AddLink which specifies whether create required
30
// directories for the child
31
func (objectOpts) Create(create bool) ObjectAddLinkOption {
core/coreiface/tests/object.go
+72
-395
@@ -1,15 +1,15 @@
1
package tests
2
3
import (
4
- "bytes"
4
"context"
6
- "encoding/hex"
7
- "io"
8
- "strings"
5
"testing"
6
7
+ dag "github.com/ipfs/boxo/ipld/merkledag"
8
+ "github.com/ipfs/boxo/path"
9
+ ipld "github.com/ipfs/go-ipld-format"
10
iface "github.com/ipfs/kubo/core/coreiface"
11
opt "github.com/ipfs/kubo/core/coreiface/options"
12
+ "github.com/stretchr/testify/require"
13
)
14
15
func (tp *TestSuite) TestObject(t *testing.T) {
@@ -20,448 +20,125 @@ func (tp *TestSuite) TestObject(t *testing.T) {
20
return nil
21
})
22
23
- t.Run("TestNew", tp.TestNew)
24
- t.Run("TestObjectPut", tp.TestObjectPut)
25
- t.Run("TestObjectGet", tp.TestObjectGet)
26
- t.Run("TestObjectData", tp.TestObjectData)
27
- t.Run("TestObjectLinks", tp.TestObjectLinks)
28
- t.Run("TestObjectStat", tp.TestObjectStat)
23
t.Run("TestObjectAddLink", tp.TestObjectAddLink)
24
t.Run("TestObjectAddLinkCreate", tp.TestObjectAddLinkCreate)
25
t.Run("TestObjectRmLink", tp.TestObjectRmLink)
32
- t.Run("TestObjectAddData", tp.TestObjectAddData)
33
- t.Run("TestObjectSetData", tp.TestObjectSetData)
26
t.Run("TestDiffTest", tp.TestDiffTest)
27
}
28
37
-func (tp *TestSuite) TestNew(t *testing.T) {
38
- ctx, cancel := context.WithCancel(context.Background())
39
- defer cancel()
40
- api, err := tp.makeAPI(t, ctx)
41
- if err != nil {
42
- t.Fatal(err)
43
- }
44
-
45
- emptyNode, err := api.Object().New(ctx)
46
- if err != nil {
47
- t.Fatal(err)
48
- }
49
-
50
- dirNode, err := api.Object().New(ctx, opt.Object.Type("unixfs-dir"))
51
- if err != nil {
52
- t.Fatal(err)
53
- }
54
-
55
- if emptyNode.String() != "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n" {
56
- t.Errorf("Unexpected emptyNode path: %s", emptyNode.String())
57
- }
58
-
59
- if dirNode.String() != "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" {
60
- t.Errorf("Unexpected dirNode path: %s", dirNode.String())
61
- }
62
-}
63
-
64
-func (tp *TestSuite) TestObjectPut(t *testing.T) {
65
- ctx, cancel := context.WithCancel(context.Background())
66
- defer cancel()
67
- api, err := tp.makeAPI(t, ctx)
68
- if err != nil {
69
- t.Fatal(err)
70
- }
71
-
72
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
73
- if err != nil {
74
- t.Fatal(err)
75
- }
76
-
77
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"YmFy"}`), opt.Object.DataType("base64")) // bar
78
- if err != nil {
79
- t.Fatal(err)
80
- }
81
-
82
- pbBytes, err := hex.DecodeString("0a0362617a")
83
- if err != nil {
84
- t.Fatal(err)
85
- }
86
-
87
- p3, err := api.Object().Put(ctx, bytes.NewReader(pbBytes), opt.Object.InputEnc("protobuf"))
88
- if err != nil {
89
- t.Fatal(err)
90
- }
91
-
92
- if p1.String() != "/ipfs/QmQeGyS87nyijii7kFt1zbe4n2PsXTFimzsdxyE9qh9TST" {
93
- t.Errorf("unexpected path: %s", p1.String())
94
- }
95
-
96
- if p2.String() != "/ipfs/QmNeYRbCibmaMMK6Du6ChfServcLqFvLJF76PzzF76SPrZ" {
97
- t.Errorf("unexpected path: %s", p2.String())
98
- }
99
-
100
- if p3.String() != "/ipfs/QmZreR7M2t7bFXAdb1V5FtQhjk4t36GnrvueLJowJbQM9m" {
101
- t.Errorf("unexpected path: %s", p3.String())
102
- }
103
-}
104
-
105
-func (tp *TestSuite) TestObjectGet(t *testing.T) {
106
- ctx, cancel := context.WithCancel(context.Background())
107
- defer cancel()
108
- api, err := tp.makeAPI(t, ctx)
109
- if err != nil {
110
- t.Fatal(err)
111
- }
112
-
113
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
114
- if err != nil {
115
- t.Fatal(err)
116
- }
117
-
118
- nd, err := api.Object().Get(ctx, p1)
119
- if err != nil {
120
- t.Fatal(err)
121
- }
122
-
123
- if string(nd.RawData()[len(nd.RawData())-3:]) != "foo" {
124
- t.Fatal("got non-matching data")
125
- }
126
-}
127
-
128
-func (tp *TestSuite) TestObjectData(t *testing.T) {
129
- ctx, cancel := context.WithCancel(context.Background())
130
- defer cancel()
131
- api, err := tp.makeAPI(t, ctx)
132
- if err != nil {
133
- t.Fatal(err)
134
- }
135
-
136
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
137
- if err != nil {
138
- t.Fatal(err)
139
- }
140
-
141
- r, err := api.Object().Data(ctx, p1)
142
- if err != nil {
143
- t.Fatal(err)
144
- }
145
-
146
- data, err := io.ReadAll(r)
147
- if err != nil {
148
- t.Fatal(err)
149
- }
150
-
151
- if string(data) != "foo" {
152
- t.Fatal("got non-matching data")
153
- }
154
-}
155
-
156
-func (tp *TestSuite) TestObjectLinks(t *testing.T) {
157
- ctx, cancel := context.WithCancel(context.Background())
158
- defer cancel()
159
- api, err := tp.makeAPI(t, ctx)
160
- if err != nil {
161
- t.Fatal(err)
162
- }
163
-
164
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
165
- if err != nil {
166
- t.Fatal(err)
167
- }
168
-
169
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`"}]}`))
170
- if err != nil {
171
- t.Fatal(err)
172
- }
173
-
174
- links, err := api.Object().Links(ctx, p2)
175
- if err != nil {
176
- t.Fatal(err)
177
- }
178
-
179
- if len(links) != 1 {
180
- t.Errorf("unexpected number of links: %d", len(links))
181
- }
182
-
183
- if links[0].Cid.String() != p1.RootCid().String() {
184
- t.Fatal("cids didn't batch")
185
- }
186
-
187
- if links[0].Name != "bar" {
188
- t.Fatal("unexpected link name")
189
- }
190
-}
191
-
192
-func (tp *TestSuite) TestObjectStat(t *testing.T) {
193
- ctx, cancel := context.WithCancel(context.Background())
194
- defer cancel()
195
- api, err := tp.makeAPI(t, ctx)
196
- if err != nil {
197
- t.Fatal(err)
198
- }
199
-
200
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
201
- if err != nil {
202
- t.Fatal(err)
203
- }
204
-
205
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`", "Size":3}]}`))
206
- if err != nil {
207
- t.Fatal(err)
208
- }
209
-
210
- stat, err := api.Object().Stat(ctx, p2)
211
- if err != nil {
212
- t.Fatal(err)
213
- }
29
+func putDagPbNode(t *testing.T, ctx context.Context, api iface.CoreAPI, data string, links []*ipld.Link) path.ImmutablePath {
30
+ dagnode := new(dag.ProtoNode)
31
215
- if stat.Cid.String() != p2.RootCid().String() {
216
- t.Error("unexpected stat.Cid")
32
+ if data != "" {
33
+ dagnode.SetData([]byte(data))
34
}
35
219
- if stat.NumLinks != 1 {
220
- t.Errorf("unexpected stat.NumLinks")
36
+ if links != nil {
37
+ err := dagnode.SetLinks(links)
38
+ require.NoError(t, err)
39
}
40
223
- if stat.BlockSize != 51 {
224
- t.Error("unexpected stat.BlockSize")
225
- }
226
-
227
- if stat.LinksSize != 47 {
228
- t.Errorf("unexpected stat.LinksSize: %d", stat.LinksSize)
229
- }
41
+ err := api.Dag().Add(ctx, dagnode)
42
+ require.NoError(t, err)
43
231
- if stat.DataSize != 4 {
232
- t.Error("unexpected stat.DataSize")
233
- }
234
-
235
- if stat.CumulativeSize != 54 {
236
- t.Error("unexpected stat.DataSize")
237
- }
44
+ return path.FromCid(dagnode.Cid())
45
}
46
47
func (tp *TestSuite) TestObjectAddLink(t *testing.T) {
48
ctx, cancel := context.WithCancel(context.Background())
49
defer cancel()
50
api, err := tp.makeAPI(t, ctx)
244
- if err != nil {
245
- t.Fatal(err)
246
- }
247
-
248
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
249
- if err != nil {
250
- t.Fatal(err)
251
- }
252
-
253
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`", "Size":3}]}`))
254
- if err != nil {
255
- t.Fatal(err)
256
- }
51
+ require.NoError(t, err)
52
+
53
+ p1 := putDagPbNode(t, ctx, api, "foo", nil)
54
+ p2 := putDagPbNode(t, ctx, api, "bazz", []*ipld.Link{
55
+ {
56
+ Name: "bar",
57
+ Cid: p1.RootCid(),
58
+ Size: 3,
59
+ },
60
+ })
61
62
p3, err := api.Object().AddLink(ctx, p2, "abc", p2)
259
- if err != nil {
260
- t.Fatal(err)
261
- }
262
-
263
- links, err := api.Object().Links(ctx, p3)
264
- if err != nil {
265
- t.Fatal(err)
266
- }
63
+ require.NoError(t, err)
64
268
- if len(links) != 2 {
269
- t.Errorf("unexpected number of links: %d", len(links))
270
- }
65
+ nd, err := api.Dag().Get(ctx, p3.RootCid())
66
+ require.NoError(t, err)
67
272
- if links[0].Name != "abc" {
273
- t.Errorf("unexpected link 0 name: %s", links[0].Name)
274
- }
275
-
276
- if links[1].Name != "bar" {
277
- t.Errorf("unexpected link 1 name: %s", links[1].Name)
278
- }
68
+ links := nd.Links()
69
+ require.Len(t, links, 2)
70
+ require.Equal(t, "abc", links[0].Name)
71
+ require.Equal(t, "bar", links[1].Name)
72
}
73
74
func (tp *TestSuite) TestObjectAddLinkCreate(t *testing.T) {
75
ctx, cancel := context.WithCancel(context.Background())
76
defer cancel()
77
api, err := tp.makeAPI(t, ctx)
285
- if err != nil {
286
- t.Fatal(err)
287
- }
288
-
289
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
290
- if err != nil {
291
- t.Fatal(err)
292
- }
293
-
294
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`", "Size":3}]}`))
295
- if err != nil {
296
- t.Fatal(err)
297
- }
78
+ require.NoError(t, err)
79
+
80
+ p1 := putDagPbNode(t, ctx, api, "foo", nil)
81
+ p2 := putDagPbNode(t, ctx, api, "bazz", []*ipld.Link{
82
+ {
83
+ Name: "bar",
84
+ Cid: p1.RootCid(),
85
+ Size: 3,
86
+ },
87
+ })
88
89
_, err = api.Object().AddLink(ctx, p2, "abc/d", p2)
300
- if err == nil {
301
- t.Fatal("expected an error")
302
- }
303
- if !strings.Contains(err.Error(), "no link by that name") {
304
- t.Fatalf("unexpected error: %s", err.Error())
305
- }
90
+ require.ErrorContains(t, err, "no link by that name")
91
92
p3, err := api.Object().AddLink(ctx, p2, "abc/d", p2, opt.Object.Create(true))
308
- if err != nil {
309
- t.Fatal(err)
310
- }
93
+ require.NoError(t, err)
94
312
- links, err := api.Object().Links(ctx, p3)
313
- if err != nil {
314
- t.Fatal(err)
315
- }
316
-
317
- if len(links) != 2 {
318
- t.Errorf("unexpected number of links: %d", len(links))
319
- }
320
-
321
- if links[0].Name != "abc" {
322
- t.Errorf("unexpected link 0 name: %s", links[0].Name)
323
- }
95
+ nd, err := api.Dag().Get(ctx, p3.RootCid())
96
+ require.NoError(t, err)
97
325
- if links[1].Name != "bar" {
326
- t.Errorf("unexpected link 1 name: %s", links[1].Name)
327
- }
98
+ links := nd.Links()
99
+ require.Len(t, links, 2)
100
+ require.Equal(t, "abc", links[0].Name)
101
+ require.Equal(t, "bar", links[1].Name)
102
}
103
104
func (tp *TestSuite) TestObjectRmLink(t *testing.T) {
105
ctx, cancel := context.WithCancel(context.Background())
106
defer cancel()
107
api, err := tp.makeAPI(t, ctx)
334
- if err != nil {
335
- t.Fatal(err)
336
- }
337
-
338
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
339
- if err != nil {
340
- t.Fatal(err)
341
- }
342
-
343
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.RootCid().String()+`", "Size":3}]}`))
344
- if err != nil {
345
- t.Fatal(err)
346
- }
108
+ require.NoError(t, err)
109
+
110
+ p1 := putDagPbNode(t, ctx, api, "foo", nil)
111
+ p2 := putDagPbNode(t, ctx, api, "bazz", []*ipld.Link{
112
+ {
113
+ Name: "bar",
114
+ Cid: p1.RootCid(),
115
+ Size: 3,
116
+ },
117
+ })
118
119
p3, err := api.Object().RmLink(ctx, p2, "bar")
349
- if err != nil {
350
- t.Fatal(err)
351
- }
352
-
353
- links, err := api.Object().Links(ctx, p3)
354
- if err != nil {
355
- t.Fatal(err)
356
- }
357
-
358
- if len(links) != 0 {
359
- t.Errorf("unexpected number of links: %d", len(links))
360
- }
361
-}
362
-
363
-func (tp *TestSuite) TestObjectAddData(t *testing.T) {
364
- ctx, cancel := context.WithCancel(context.Background())
365
- defer cancel()
366
- api, err := tp.makeAPI(t, ctx)
367
- if err != nil {
368
- t.Fatal(err)
369
- }
370
-
371
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
372
- if err != nil {
373
- t.Fatal(err)
374
- }
375
-
376
- p2, err := api.Object().AppendData(ctx, p1, strings.NewReader("bar"))
377
- if err != nil {
378
- t.Fatal(err)
379
- }
380
-
381
- r, err := api.Object().Data(ctx, p2)
382
- if err != nil {
383
- t.Fatal(err)
384
- }
385
-
386
- data, err := io.ReadAll(r)
387
- if err != nil {
388
- t.Fatal(err)
389
- }
390
-
391
- if string(data) != "foobar" {
392
- t.Error("unexpected data")
393
- }
394
-}
395
-
396
-func (tp *TestSuite) TestObjectSetData(t *testing.T) {
397
- ctx, cancel := context.WithCancel(context.Background())
398
- defer cancel()
399
- api, err := tp.makeAPI(t, ctx)
400
- if err != nil {
401
- t.Fatal(err)
402
- }
403
-
404
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
405
- if err != nil {
406
- t.Fatal(err)
407
- }
120
+ require.NoError(t, err)
121
409
- p2, err := api.Object().SetData(ctx, p1, strings.NewReader("bar"))
410
- if err != nil {
411
- t.Fatal(err)
412
- }
413
-
414
- r, err := api.Object().Data(ctx, p2)
415
- if err != nil {
416
- t.Fatal(err)
417
- }
122
+ nd, err := api.Dag().Get(ctx, p3.RootCid())
123
+ require.NoError(t, err)
124
419
- data, err := io.ReadAll(r)
420
- if err != nil {
421
- t.Fatal(err)
422
- }
423
-
424
- if string(data) != "bar" {
425
- t.Error("unexpected data")
426
- }
125
+ links := nd.Links()
126
+ require.Len(t, links, 0)
127
}
128
129
func (tp *TestSuite) TestDiffTest(t *testing.T) {
130
ctx, cancel := context.WithCancel(context.Background())
131
defer cancel()
132
api, err := tp.makeAPI(t, ctx)
433
- if err != nil {
434
- t.Fatal(err)
435
- }
436
-
437
- p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
438
- if err != nil {
439
- t.Fatal(err)
440
- }
133
+ require.NoError(t, err)
134
442
- p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bar"}`))
443
- if err != nil {
444
- t.Fatal(err)
445
- }
135
+ p1 := putDagPbNode(t, ctx, api, "foo", nil)
136
+ p2 := putDagPbNode(t, ctx, api, "bar", nil)
137
138
changes, err := api.Object().Diff(ctx, p1, p2)
448
- if err != nil {
449
- t.Fatal(err)
450
- }
451
-
452
- if len(changes) != 1 {
453
- t.Fatal("unexpected changes len")
454
- }
455
-
456
- if changes[0].Type != iface.DiffMod {
457
- t.Fatal("unexpected change type")
458
- }
459
-
460
- if changes[0].Before.String() != p1.String() {
461
- t.Fatal("unexpected before path")
462
- }
463
-
464
- if changes[0].After.String() != p2.String() {
465
- t.Fatal("unexpected before path")
466
- }
139
+ require.NoError(t, err)
140
+ require.Len(t, changes, 1)
141
+ require.Equal(t, iface.DiffMod, changes[0].Type)
142
+ require.Equal(t, p1.String(), changes[0].Before.String())
143
+ require.Equal(t, p2.String(), changes[0].After.String())
144
}
core/coreiface/tests/unixfs.go
+5
-15
@@ -630,16 +630,11 @@ func (tp *TestSuite) TestGetDir(t *testing.T) {
630
}
631
p := path.FromCid(edir.Cid())
632
633
- emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir"))
634
- if err != nil {
635
- t.Fatal(err)
636
- }
637
-
638
- if p.String() != path.FromCid(emptyDir.Cid()).String() {
639
- t.Fatalf("expected path %s, got: %s", emptyDir.Cid(), p.String())
633
+ if p.String() != path.FromCid(edir.Cid()).String() {
634
+ t.Fatalf("expected path %s, got: %s", edir.Cid(), p.String())
635
}
636
642
- r, err := api.Unixfs().Get(ctx, path.FromCid(emptyDir.Cid()))
637
+ r, err := api.Unixfs().Get(ctx, path.FromCid(edir.Cid()))
638
if err != nil {
639
t.Fatal(err)
640
}
@@ -779,17 +774,12 @@ func (tp *TestSuite) TestLsEmptyDir(t *testing.T) {
774
t.Fatal(err)
775
}
776
782
- _, err = api.Unixfs().Add(ctx, files.NewSliceDirectory([]files.DirEntry{}))
783
- if err != nil {
784
- t.Fatal(err)
785
- }
786
-
787
- emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir"))
777
+ p, err := api.Unixfs().Add(ctx, files.NewSliceDirectory([]files.DirEntry{}))
778
if err != nil {
779
t.Fatal(err)
780
}
781
792
- links, err := api.Unixfs().Ls(ctx, path.FromCid(emptyDir.Cid()))
782
+ links, err := api.Unixfs().Ls(ctx, p)
783
if err != nil {
784
t.Fatal(err)
785
}
docs/changelogs/v0.28.md
+5
@@ -8,6 +8,7 @@
8
- [🔦 Highlights](#-highlights)
9
- [RPC client: removed deprecated DHT API](#rpc-client-removed-deprecated-dht-api)
10
- [Gateway: `/api/v0` is removed](#gateway-apiv0-is-removed)
11
+ - [Removed deprecated Object API commands](#removed-deprecated-object-api-commands)
12
- [📝 Changelog](#-changelog)
13
- [👨👩👧👦 Contributors](#-contributors)
14
@@ -23,6 +24,10 @@ The legacy subset of the Kubo RPC that was available via the Gateway port and wa
24
25
If you have a legacy software that relies on this behavior, and want to expose parts of `/api/v0` next to `/ipfs`, use reverse-proxy in front of Kubo to mount both Gateway and RPC on the same port. NOTE: exposing RPC to the internet comes with security risk: make sure to specify access control via [API.Authorizations](https://github.com/ipfs/kubo/blob/master/docs/config.md#apiauthorizations).
26
27
+#### Removed deprecated Object API commands
28
+
29
+The Object API commands deprecated back in [2021](https://github.com/ipfs/kubo/issues/7936) have been removed, except for `object diff`, `object patch add-link` and `object patch rm-link`, whose alternatives have not yet been built (see issues [4801](https://github.com/ipfs/kubo/issues/4801) and [4782](https://github.com/ipfs/kubo/issues/4782)).
30
+
31
### 📝 Changelog
32
33
### 👨👩👧👦 Contributors
docs/implement-api-bindings.md
+2
-3
@@ -39,10 +39,9 @@ function calls. For example:
39
#### CLI API Transport
40
41
In the commandline, IPFS uses a traditional flag and arg-based mapping, where:
42
-- the first arguments selects the command, as in git - e.g. `ipfs object get`
42
+- the first arguments selects the command, as in git - e.g. `ipfs dag get`
43
- the flags specify options - e.g. `--enc=protobuf -q`
44
-- the rest are positional arguments - e.g.
45
- `ipfs object patch <hash1> add-linkfoo <hash2>`
44
+- the rest are positional arguments - e.g. `ipfs key rename <name> <newName>`
45
- files are specified by filename, or through stdin
46
47
(NOTE: When kubo runs the daemon, the CLI API is actually converted to HTTP
test/cli/basic_commands_test.go
-3
@@ -147,7 +147,6 @@ func TestCommandDocsWidth(t *testing.T) {
147
"ipfs swarm addrs listen": true,
148
"ipfs dag resolve": true,
149
"ipfs dag get": true,
150
- "ipfs object stat": true,
150
"ipfs pin remote add": true,
151
"ipfs config show": true,
152
"ipfs config edit": true,
@@ -164,8 +163,6 @@ func TestCommandDocsWidth(t *testing.T) {
163
"ipfs object diff": true,
164
"ipfs object patch add-link": true,
165
"ipfs name": true,
167
- "ipfs object patch append-data": true,
168
- "ipfs object patch set-data": true,
166
"ipfs diag profile": true,
167
"ipfs diag cmds": true,
168
"ipfs swarm addrs local": true,
test/sharness/t0050-block-data/testPut.pb
renamed
test/sharness/t0050-block.sh
+11
-11
@@ -42,12 +42,12 @@ test_expect_success "'ipfs block put' output looks good" '
42
'
43
44
test_expect_success "can set cid codec on block put" '
45
- CODEC_HASH=$(ipfs block put --cid-codec=dag-pb ../t0051-object-data/testPut.pb)
45
+ CODEC_HASH=$(ipfs block put --cid-codec=dag-pb ../t0050-block-data/testPut.pb)
46
'
47
48
test_expect_success "block get output looks right" '
49
ipfs block get $CODEC_HASH > pb_block_out &&
50
- test_cmp pb_block_out ../t0051-object-data/testPut.pb
50
+ test_cmp pb_block_out ../t0050-block-data/testPut.pb
51
'
52
53
#
@@ -210,33 +210,33 @@ test_expect_success "multi-block 'ipfs block rm -q' produces no output" '
210
# --format used 'protobuf' for 'dag-pb' which was invalid, but we keep
211
# for backward-compatibility
212
test_expect_success "can set deprecated --format=protobuf on block put" '
213
- HASH=$(ipfs block put --format=protobuf ../t0051-object-data/testPut.pb)
213
+ HASH=$(ipfs block put --format=protobuf ../t0050-block-data/testPut.pb)
214
'
215
216
test_expect_success "created an object correctly!" '
217
- ipfs object get $HASH > obj_out &&
218
- echo "{\"Links\":[],\"Data\":\"test json for sharness test\"}" > obj_exp &&
217
+ ipfs dag get $HASH > obj_out &&
218
+ echo -n "{\"Data\":{\"/\":{\"bytes\":\"dGVzdCBqc29uIGZvciBzaGFybmVzcyB0ZXN0\"}},\"Links\":[]}" > obj_exp &&
219
test_cmp obj_out obj_exp
220
'
221
222
test_expect_success "block get output looks right" '
223
ipfs block get $HASH > pb_block_out &&
224
- test_cmp pb_block_out ../t0051-object-data/testPut.pb
224
+ test_cmp pb_block_out ../t0050-block-data/testPut.pb
225
'
226
227
test_expect_success "can set --cid-codec=dag-pb on block put" '
228
- HASH=$(ipfs block put --cid-codec=dag-pb ../t0051-object-data/testPut.pb)
228
+ HASH=$(ipfs block put --cid-codec=dag-pb ../t0050-block-data/testPut.pb)
229
'
230
231
test_expect_success "created an object correctly!" '
232
- ipfs object get $HASH > obj_out &&
233
- echo "{\"Links\":[],\"Data\":\"test json for sharness test\"}" > obj_exp &&
232
+ ipfs dag get $HASH > obj_out &&
233
+ echo -n "{\"Data\":{\"/\":{\"bytes\":\"dGVzdCBqc29uIGZvciBzaGFybmVzcyB0ZXN0\"}},\"Links\":[]}" > obj_exp &&
234
test_cmp obj_out obj_exp
235
'
236
237
test_expect_success "block get output looks right" '
238
ipfs block get $HASH > pb_block_out &&
239
- test_cmp pb_block_out ../t0051-object-data/testPut.pb
239
+ test_cmp pb_block_out ../t0050-block-data/testPut.pb
240
'
241
242
test_expect_success "can set multihash type and length on block put with --format=raw (deprecated)" '
@@ -248,7 +248,7 @@ test_expect_success "output looks good" '
248
'
249
250
test_expect_success "can't use both legacy format and custom cid-codec at the same time" '
251
- test_expect_code 1 ipfs block put --format=dag-cbor --cid-codec=dag-json < ../t0051-object-data/testPut.pb 2> output &&
251
+ test_expect_code 1 ipfs block put --format=dag-cbor --cid-codec=dag-json < ../t0050-block-data/testPut.pb 2> output &&
252
test_should_contain "unable to use \"format\" (deprecated) and a custom \"cid-codec\" at the same time" output
253
'
254
test/sharness/t0051-object-data/UTF-8-test.txt
Binary files a/test/sharness/t0051-object-data/UTF-8-test.txt and /dev/null differ
test/sharness/t0051-object-data/brokenPut.json
deleted
-5
@@ -1,5 +0,0 @@
1
-{
2
- "this": "should",
3
- "return": "an",
4
- "error":"not valid dag object"
5
-}
\ No newline at end of file
test/sharness/t0051-object-data/brokenPut.xml
deleted
-1
@@ -1 +0,0 @@
1
-<Noodles><Spaghetti>This is not a valid dag object fail</Spaghetti></Noodles>
test/sharness/t0051-object-data/expected_getOut
deleted
-1
@@ -1 +0,0 @@
1
-{"Links":[],"Data":"\b\u0002\u0012\nHello Mars\u0018\n"}
test/sharness/t0051-object-data/mixed.json
deleted
-5
@@ -1,5 +0,0 @@
1
-{"Data": "another",
2
- "Links": [
3
- {"Name": "some link", "Hash": "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V", "Size": 8},
4
- {"Name": "inlined", "Hash": "z4CrgyEyhm4tAw1pgzQtNNuP7", "Size": 14}
5
-]}
test/sharness/t0051-object-data/testPut.json
deleted
-3
@@ -1,3 +0,0 @@
1
-{
2
- "Data": "test json for sharness test"
3
-}
test/sharness/t0051-object-data/testPut.xml
deleted
-1
@@ -1 +0,0 @@
1
-<Node><Data>Test xml for sharness test</Data></Node>
test/sharness/t0051-object.sh
+19
-344
@@ -27,204 +27,21 @@ test_patch_create_path() {
27
}
28
29
test_object_cmd() {
30
-
31
- test_expect_success "'ipfs add testData' succeeds" '
32
- printf "Hello Mars" >expected_in &&
33
- ipfs add expected_in >actual_Addout
34
- '
35
-
36
- test_expect_success "'ipfs add testData' output looks good" '
37
- HASH="QmWkHFpYBZ9mpPRreRbMhhYWXfUhBAue3JkbbpFqwowSRb" &&
38
- echo "added $HASH expected_in" >expected_Addout &&
39
- test_cmp expected_Addout actual_Addout
40
- '
41
-
42
- test_expect_success "'ipfs object get' succeeds" '
43
- ipfs object get $HASH >actual_getOut
44
- '
45
-
46
- test_expect_success "'ipfs object get' output looks good" '
47
- test_cmp ../t0051-object-data/expected_getOut actual_getOut
48
- '
49
-
50
- test_expect_success "'ipfs object get' can specify data encoding as base64" '
51
- ipfs object get --data-encoding base64 $HASH > obj_out &&
52
- echo "{\"Links\":[],\"Data\":\"CAISCkhlbGxvIE1hcnMYCg==\"}" > obj_exp &&
53
- test_cmp obj_out obj_exp
54
- '
55
-
56
- test_expect_success "'ipfs object get' can specify data encoding as text" '
57
- echo "{\"Links\":[],\"Data\":\"Hello Mars\"}" | ipfs object put &&
58
- ipfs object get --data-encoding text QmS3hVY6eYrMQ6L22agwrx3YHBEsc3LJxVXCtyQHqRBukH > obj_out &&
59
- echo "{\"Links\":[],\"Data\":\"Hello Mars\"}" > obj_exp &&
60
- test_cmp obj_out obj_exp
61
- '
62
-
63
- test_expect_failure "'ipfs object get' requires known data encoding" '
64
- ipfs object get --data-encoding nonsensical-encoding $HASH
65
- '
66
-
67
- test_expect_success "'ipfs object stat' succeeds" '
68
- ipfs object stat $HASH >actual_stat
69
- '
70
-
71
- test_expect_success "'ipfs object get' output looks good" '
72
- echo "NumLinks: 0" > expected_stat &&
73
- echo "BlockSize: 18" >> expected_stat &&
74
- echo "LinksSize: 2" >> expected_stat &&
75
- echo "DataSize: 16" >> expected_stat &&
76
- echo "CumulativeSize: 18" >> expected_stat &&
77
- test_cmp expected_stat actual_stat
78
- '
79
-
80
- test_expect_success "'ipfs object put file.json' succeeds" '
81
- ipfs object put ../t0051-object-data/testPut.json > actual_putOut
82
- '
83
-
84
- test_expect_success "'ipfs object put file.json' output looks good" '
85
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
86
- printf "added $HASH\n" > expected_putOut &&
87
- test_cmp expected_putOut actual_putOut
88
- '
89
-
90
- test_expect_success "'ipfs object put --quiet file.json' succeeds" '
91
- ipfs object put --quiet ../t0051-object-data/testPut.json > actual_putOut
92
- '
93
-
94
- test_expect_success "'ipfs object put --quiet file.json' output looks good" '
95
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
96
- printf "$HASH\n" > expected_putOut &&
97
- test_cmp expected_putOut actual_putOut
98
- '
99
-
100
- test_expect_success "'ipfs object put file.xml' succeeds" '
101
- ipfs object put ../t0051-object-data/testPut.xml --inputenc=xml > actual_putOut
102
- '
103
-
104
- test_expect_success "'ipfs object put file.xml' output looks good" '
105
- HASH="QmQzNKUHy4HyEUGkqKe3q3t796ffPLQXYCkHCcXUNT5JNK" &&
106
- printf "added $HASH\n" > expected_putOut &&
107
- test_cmp expected_putOut actual_putOut
108
- '
109
-
110
- test_expect_success "'ipfs object put' from stdin succeeds" '
111
- cat ../t0051-object-data/testPut.xml | ipfs object put --inputenc=xml > actual_putStdinOut
112
- '
113
-
114
- test_expect_failure "'ipfs object put broken.xml' should fail" '
115
- test_expect_code 1 ipfs object put ../t0051-object-data/brokenPut.xml --inputenc=xml 2>actual_putBrokenErr >actual_putBroken
116
- '
117
-
118
- test_expect_failure "'ipfs object put broken.hxml' output looks good" '
119
- touch expected_putBroken &&
120
- printf "Error: no data or links in this node\n" > expected_putBrokenErr &&
121
- test_cmp expected_putBroken actual_putBroken &&
122
- test_cmp expected_putBrokenErr actual_putBrokenErr
123
- '
124
- test_expect_success "'ipfs object get --enc=xml' succeeds" '
125
- ipfs object get --enc=xml $HASH >utf8_xml
126
- '
127
-
128
- test_expect_success "'ipfs object put --inputenc=xml' succeeds" '
129
- ipfs object put --inputenc=xml <utf8_xml >actual
130
- '
131
-
132
- test_expect_failure "'ipfs object put --inputenc=xml' output looks good" '
133
- echo "added $HASH\n" >expected &&
134
- test_cmp expected actual
135
- '
136
-
137
- test_expect_success "'ipfs object put file.pb' succeeds" '
138
- ipfs object put --inputenc=protobuf ../t0051-object-data/testPut.pb > actual_putOut
139
- '
140
-
141
- test_expect_success "'ipfs object put file.pb' output looks good" '
142
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
143
- printf "added $HASH\n" > expected_putOut &&
144
- test_cmp expected_putOut actual_putOut
145
- '
146
-
147
- test_expect_success "'ipfs object put' from stdin succeeds" '
148
- cat ../t0051-object-data/testPut.json | ipfs object put > actual_putStdinOut
149
- '
150
-
151
- test_expect_success "'ipfs object put' from stdin output looks good" '
152
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
153
- printf "added $HASH\n" > expected_putStdinOut &&
154
- test_cmp expected_putStdinOut actual_putStdinOut
155
- '
156
-
157
- test_expect_success "'ipfs object put' from stdin (pb) succeeds" '
158
- cat ../t0051-object-data/testPut.pb | ipfs object put --inputenc=protobuf > actual_putPbStdinOut
159
- '
160
-
161
- test_expect_success "'ipfs object put' from stdin (pb) output looks good" '
162
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
163
- printf "added $HASH\n" > expected_putStdinOut &&
164
- test_cmp expected_putStdinOut actual_putPbStdinOut
165
- '
166
-
167
- test_expect_success "'ipfs object put broken.json' should fail" '
168
- test_expect_code 1 ipfs object put ../t0051-object-data/brokenPut.json 2>actual_putBrokenErr >actual_putBroken
169
- '
170
-
171
- test_expect_success "'ipfs object put broken.hjson' output looks good" '
172
- touch expected_putBroken &&
173
- printf "Error: json: unknown field \"this\"\n" > expected_putBrokenErr &&
174
- test_cmp expected_putBroken actual_putBroken &&
175
- test_cmp expected_putBrokenErr actual_putBrokenErr
176
- '
177
-
178
- test_expect_success "setup: add UTF-8 test file" '
179
- HASH="QmNY5sQeH9ttVCg24sizH71dNbcZTpGd7Yb3YwsKZ4jiFP" &&
180
- ipfs add ../t0051-object-data/UTF-8-test.txt >actual &&
181
- echo "added $HASH UTF-8-test.txt" >expected &&
182
- test_cmp expected actual
183
- '
184
-
185
- test_expect_success "'ipfs object get --enc=json' succeeds" '
186
- ipfs object get --enc=json $HASH >utf8_json
187
- '
188
-
189
- test_expect_success "'ipfs object put --inputenc=json' succeeds" '
190
- ipfs object put --inputenc=json <utf8_json >actual
191
- '
192
-
193
- test_expect_failure "'ipfs object put --inputenc=json' output looks good" '
194
- echo "added $HASH" >expected &&
195
- test_cmp expected actual
196
- '
197
-
198
- test_expect_success "'ipfs object put --pin' succeeds" '
199
- HASH="QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V" &&
200
- echo "added $HASH" >expected &&
201
- echo "{ \"Data\": \"abc\" }" | ipfs object put --pin >actual
202
- '
203
-
204
- test_expect_success "'ipfs object put --pin' output looks good" '
205
- echo "added $HASH" >expected &&
206
- test_cmp expected actual
207
- '
208
-
209
- test_expect_success "after gc, objects still accessible" '
210
- ipfs repo gc > /dev/null &&
211
- ipfs refs -r --timeout=2s $HASH > /dev/null
212
- '
30
+ EMPTY_DIR=$(echo '{"Links":[]}' | ipfs dag put --store-codec dag-pb)
31
+ EMPTY_UNIXFS_DIR=$(echo '{"Data":{"/":{"bytes":"CAE"}},"Links":[]}' | ipfs dag put --store-codec dag-pb)
32
33
test_expect_success "'ipfs object patch' should work (no unixfs-dir)" '
215
- EMPTY_DIR=$(ipfs object new) &&
34
OUTPUT=$(ipfs object patch $EMPTY_DIR add-link foo $EMPTY_DIR) &&
217
- ipfs object stat $OUTPUT
35
+ ipfs dag stat $OUTPUT
36
'
37
38
test_expect_success "'ipfs object patch' should work" '
221
- EMPTY_DIR=$(ipfs object new unixfs-dir) &&
222
- OUTPUT=$(ipfs object patch $EMPTY_DIR add-link foo $EMPTY_DIR) &&
223
- ipfs object stat $OUTPUT
39
+ OUTPUT=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link foo $EMPTY_UNIXFS_DIR) &&
40
+ ipfs dag stat $OUTPUT
41
'
42
43
test_expect_success "'ipfs object patch' check output block size" '
227
- DIR=$(ipfs object new unixfs-dir)
44
+ DIR=$EMPTY_UNIXFS_DIR
45
for i in {1..13}
46
do
47
DIR=$(ipfs object patch "$DIR" add-link "$DIR.jpg" "$DIR")
@@ -241,32 +58,20 @@ test_object_cmd() {
58
test_expect_code 0 ipfs object patch --allow-big-block=true "$DIR" add-link "$DIR.jpg" "$DIR"
59
'
60
244
- test_expect_success "'ipfs object new foo' shouldn't crash" '
245
- test_expect_code 1 ipfs object new foo
246
- '
247
-
248
- test_expect_success "'ipfs object links' gives the correct results" '
249
- echo "$EMPTY_DIR" 4 foo > expected &&
250
- ipfs object links "$OUTPUT" > actual &&
251
- test_cmp expected actual
252
- '
253
-
61
test_expect_success "'ipfs object patch add-link' should work with paths" '
255
- EMPTY_DIR=$(ipfs object new unixfs-dir) &&
256
- N1=$(ipfs object patch $EMPTY_DIR add-link baz $EMPTY_DIR) &&
257
- N2=$(ipfs object patch $EMPTY_DIR add-link bar $N1) &&
258
- N3=$(ipfs object patch $EMPTY_DIR add-link foo /ipfs/$N2/bar) &&
259
- ipfs object stat /ipfs/$N3 > /dev/null &&
260
- ipfs object stat $N3/foo > /dev/null &&
261
- ipfs object stat /ipfs/$N3/foo/baz > /dev/null
62
+ N1=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link baz $EMPTY_UNIXFS_DIR) &&
63
+ N2=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link bar $N1) &&
64
+ N3=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link foo /ipfs/$N2/bar) &&
65
+ ipfs dag stat /ipfs/$N3 > /dev/null &&
66
+ ipfs dag stat $N3/foo > /dev/null &&
67
+ ipfs dag stat /ipfs/$N3/foo/baz > /dev/null
68
'
69
70
test_expect_success "'ipfs object patch add-link' allow linking IPLD objects" '
265
- EMPTY_DIR=$(ipfs object new unixfs-dir) &&
71
OBJ=$(echo "123" | ipfs dag put) &&
267
- N1=$(ipfs object patch $EMPTY_DIR add-link foo $OBJ) &&
72
+ N1=$(ipfs object patch $EMPTY_UNIXFS_DIR add-link foo $OBJ) &&
73
269
- ipfs object stat /ipfs/$N1 > /dev/null &&
74
+ ipfs dag stat /ipfs/$N1 > /dev/null &&
75
ipfs resolve /ipfs/$N1/foo > actual &&
76
echo /ipfs/$OBJ > expected &&
77
@@ -274,7 +79,7 @@ test_object_cmd() {
79
'
80
81
test_expect_success "object patch creation looks right" '
277
- echo "QmPc73aWK9dgFBXe86P4PvQizHo9e5Qt7n7DAMXWuigFuG" > hash_exp &&
82
+ echo "bafybeiakusqwohnt7bs75kx6jhmt4oi47l634bmudxfv4qxhpco6xuvgna" > hash_exp &&
83
echo $N3 > hash_actual &&
84
test_cmp hash_exp hash_actual
85
'
@@ -282,7 +87,7 @@ test_object_cmd() {
87
test_expect_success "multilayer ipfs patch works" '
88
echo "hello world" > hwfile &&
89
FILE=$(ipfs add -q hwfile) &&
285
- EMPTY=$(ipfs object new unixfs-dir) &&
90
+ EMPTY=$EMPTY_UNIXFS_DIR &&
91
ONE=$(ipfs object patch $EMPTY add-link b $EMPTY) &&
92
TWO=$(ipfs object patch $EMPTY add-link a $ONE) &&
93
ipfs object patch $TWO add-link a/b/c $FILE > multi_patch
@@ -293,49 +98,12 @@ test_object_cmd() {
98
test_cmp hwfile hwfile_out
99
'
100
296
- test_expect_success "ipfs object stat path succeeds" '
297
- ipfs object stat $(cat multi_patch)/a > obj_stat_out
298
- '
299
-
300
- test_expect_success "ipfs object stat output looks good" '
301
- echo "NumLinks: 1" > obj_stat_exp &&
302
- echo "BlockSize: 47" >> obj_stat_exp &&
303
- echo "LinksSize: 45" >> obj_stat_exp &&
304
- echo "DataSize: 2" >> obj_stat_exp &&
305
- echo "CumulativeSize: 114" >> obj_stat_exp &&
306
-
307
- test_cmp obj_stat_exp obj_stat_out
308
- '
309
-
310
- test_expect_success "'ipfs object stat --human' succeeds" '
311
- ipfs object stat $(cat multi_patch)/a --human > obj_stat_human_out
312
- '
313
-
314
- test_expect_success "ipfs object stat --human output looks good" '
315
- echo "NumLinks: 1" > obj_stat_human_exp &&
316
- echo "BlockSize: 47" >> obj_stat_human_exp &&
317
- echo "LinksSize: 45" >> obj_stat_human_exp &&
318
- echo "DataSize: 2" >> obj_stat_human_exp &&
319
- echo "CumulativeSize: 114 B" >> obj_stat_human_exp &&
320
-
321
- test_cmp obj_stat_human_exp obj_stat_human_out
322
- '
323
-
324
- test_expect_success "should have created dir within a dir" '
325
- ipfs ls $OUTPUT > patched_output
326
- '
327
-
328
- test_expect_success "output looks good" '
329
- echo "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn - foo/" > patched_exp &&
330
- test_cmp patched_exp patched_output
331
- '
332
-
101
test_expect_success "can remove the directory" '
102
ipfs object patch $OUTPUT rm-link foo > rmlink_output
103
'
104
105
test_expect_success "output should be empty" '
338
- echo QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn > rmlink_exp &&
106
+ echo bafybeiczsscdsbs7ffqz55asqdf3smv6klcw3gofszvwlyarci47bgf354 > rmlink_exp &&
107
test_cmp rmlink_exp rmlink_output
108
'
109
@@ -344,7 +112,7 @@ test_object_cmd() {
112
'
113
114
test_expect_success "output looks good" '
347
- echo "QmZD3r9cZjzU8huNY2JS9TC6n8daDfT8TmE8zBSqG31Wvq" > multi_link_rm_exp &&
115
+ echo "bafybeicourxysmtbe5hacxqico4d5hyvh7gqkrwlmqa4ew7zufn3pj3juu" > multi_link_rm_exp &&
116
test_cmp multi_link_rm_exp multi_link_rm_out
117
'
118
@@ -355,7 +123,7 @@ test_object_cmd() {
123
test_patch_create_path $EMPTY a/b/b/b/b $FILE
124
125
test_expect_success "can create blank object" '
358
- BLANK=$(ipfs object new)
126
+ BLANK=$EMPTY_DIR
127
'
128
129
test_patch_create_path $BLANK a $FILE
@@ -363,98 +131,6 @@ test_object_cmd() {
131
test_expect_success "create bad path fails" '
132
test_must_fail ipfs object patch $EMPTY add-link --create / $FILE
133
'
366
-
367
- test_expect_success "patch set-data works" '
368
- EMPTY=$(ipfs object new) &&
369
- HASH=$(printf "foo" | ipfs object patch $EMPTY set-data)
370
- '
371
-
372
- test_expect_success "output looks good" '
373
- echo "{\"Links\":[],\"Data\":\"foo\"}" > exp_data_set &&
374
- ipfs object get $HASH > actual_data_set &&
375
- test_cmp exp_data_set actual_data_set
376
- '
377
-
378
- test_expect_success "patch append-data works" '
379
- HASH=$(printf "bar" | ipfs object patch $HASH append-data)
380
- '
381
-
382
- test_expect_success "output looks good" '
383
- echo "{\"Links\":[],\"Data\":\"foobar\"}" > exp_data_append &&
384
- ipfs object get $HASH > actual_data_append &&
385
- test_cmp exp_data_append actual_data_append
386
- '
387
-
388
- #
389
- # CidBase Tests
390
- #
391
-
392
- test_expect_success "'ipfs object put file.json --cid-base=base32' succeeds" '
393
- ipfs object put --cid-base=base32 ../t0051-object-data/testPut.json > actual_putOut
394
- '
395
-
396
- test_expect_success "'ipfs object put file.json --cid-base=base32' output looks good" '
397
- HASH="QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD" &&
398
- printf "added $HASH\n" > expected_putOut &&
399
- test_cmp expected_putOut actual_putOut
400
- '
401
-
402
- test_expect_success "'ipfs object put file.json --cid-base=base32 --upgrade-cidv0-in-output=true' succeeds" '
403
- ipfs object put --cid-base=base32 --upgrade-cidv0-in-output=true ../t0051-object-data/testPut.json > actual_putOut
404
- '
405
-
406
- test_expect_success "'ipfs object put file.json --cid-base=base32 --upgrade-cidv0-in-output=true' output looks good" '
407
- HASH=$(ipfs cid base32 "QmUTSAdDi2xsNkDtLqjFgQDMEn5di3Ab9eqbrt4gaiNbUD") &&
408
- printf "added $HASH\n" > expected_putOut &&
409
- test_cmp expected_putOut actual_putOut
410
- '
411
-
412
- test_expect_success "'insert json dag with both CidV0 and CidV1 links'" '
413
- MIXED=$(ipfs object put ../t0051-object-data/mixed.json -q) &&
414
- echo $MIXED
415
- '
416
-
417
- test_expect_success "ipfs object get then put creates identical object with --cid-base=base32" '
418
- ipfs object get --cid-base=base32 $MIXED > mixedv2.json &&
419
- MIXED2=$(ipfs object put -q mixedv2.json) &&
420
- echo "$MIXED =? $MIXED2" &&
421
- test "$MIXED" = "$MIXED2"
422
- '
423
-
424
- HASHv0=QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V
425
- HASHv1=bafkqadsimvwgy3zajb2w2yloeefau
426
-
427
- test_expect_success "ipfs object get with --cid-base=base32 uses base32 for CidV1 link only" '
428
- ipfs object get --cid-base=base32 $MIXED > mixed.actual &&
429
- grep -q $HASHv0 mixed.actual &&
430
- grep -q $(ipfs cid base32 $HASHv1) mixed.actual
431
- '
432
-
433
- test_expect_success "ipfs object links --cid-base=base32 --upgrade-cidv0-in-output=true converts both links" '
434
- ipfs object links --cid-base=base32 --upgrade-cidv0-in-output=true $MIXED | awk "{print \$1}" | sort > links.actual &&
435
- echo $(ipfs cid base32 $HASHv1) > links.expected
436
- echo $(ipfs cid base32 $HASHv0) >> links.expected
437
- test_cmp links.actual links.expected
438
- '
439
-}
440
-
441
-test_object_content_type() {
442
-
443
- test_expect_success "'ipfs object get --encoding=protobuf' returns the correct content type" '
444
- curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=protobuf" | grep -q "^Content-Type: application/protobuf"
445
- '
446
-
447
- test_expect_success "'ipfs object get --encoding=json' returns the correct content type" '
448
- curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=json" | grep -q "^Content-Type: application/json"
449
- '
450
-
451
- test_expect_success "'ipfs object get --encoding=text' returns the correct content type" '
452
- curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=text" | grep -q "^Content-Type: text/plain"
453
- '
454
-
455
- test_expect_success "'ipfs object get --encoding=xml' returns the correct content type" '
456
- curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=xml" | grep -q "^Content-Type: application/xml"
457
- '
134
}
135
136
# should work offline
@@ -463,7 +139,6 @@ test_object_cmd
139
# should work online
140
test_launch_ipfs_daemon
141
test_object_cmd
466
-test_object_content_type
142
test_kill_ipfs_daemon
143
144
test_done
test/sharness/t0081-repo-pinning.sh
+3
-3
@@ -114,8 +114,8 @@ test_expect_success "objects are there" '
114
'
115
116
# saving this output for later
117
-test_expect_success "ipfs object links $HASH_DIR1 works" '
118
- ipfs object links $HASH_DIR1 > DIR1_objlink
117
+test_expect_success "ipfs dag get $HASH_DIR1 works" '
118
+ ipfs dag get $HASH_DIR1 | jq -r ".Links[] | .Hash | .[\"/\"]" > DIR1_objlink
119
'
120
121
@@ -224,7 +224,7 @@ test_expect_success "some objects are still there" '
224
ipfs cat "$HASH_FILE1" >>actual8 &&
225
ipfs ls "$HASH_DIR4" >>actual8 &&
226
ipfs ls "$HASH_DIR2" >>actual8 &&
227
- ipfs object links "$HASH_DIR1" >>actual8 &&
227
+ ipfs dag get "$HASH_DIR1" | jq -r ".Links[] | .Hash | .[\"/\"]" >>actual8 &&
228
test_cmp expected8 actual8
229
'
230
test/sharness/t0090-get.sh
+3
-3
@@ -157,13 +157,13 @@ test_get_cmd() {
157
test_get_fail() {
158
test_expect_success "create an object that has unresolvable links" '
159
cat <<-\EOF >bad_object &&
160
-{ "Links": [ { "Name": "foo", "Hash": "QmZzaC6ydNXiR65W8VjGA73ET9MZ6VFAqUT1ngYMXcpihn", "Size": 1897 }, { "Name": "bar", "Hash": "Qmd4mG6pDFDmDTn6p3hX1srP8qTbkyXKj5yjpEsiHDX3u8", "Size": 56 }, { "Name": "baz", "Hash": "QmUTjwRnG28dSrFFVTYgbr6LiDLsBmRr2SaUSTGheK2YqG", "Size": 24266 } ], "Data": "\b\u0001" }
160
+{"Data":{"/":{"bytes":"CAE"}},"Links":[{"Hash":{"/":"Qmd4mG6pDFDmDTn6p3hX1srP8qTbkyXKj5yjpEsiHDX3u8"},"Name":"bar","Tsize":56},{"Hash":{"/":"QmUTjwRnG28dSrFFVTYgbr6LiDLsBmRr2SaUSTGheK2YqG"},"Name":"baz","Tsize":24266},{"Hash":{"/":"QmZzaC6ydNXiR65W8VjGA73ET9MZ6VFAqUT1ngYMXcpihn"},"Name":"foo","Tsize":1897}]}
161
EOF
162
- cat bad_object | ipfs object put > put_out
162
+ cat bad_object | ipfs dag put --store-codec dag-pb > put_out
163
'
164
165
test_expect_success "output looks good" '
166
- echo "added QmaGidyrnX8FMbWJoxp8HVwZ1uRKwCyxBJzABnR1S2FVUr" > put_exp &&
166
+ echo "bafybeifrjjol3gixedca6etdwccnvwfvhurc4wb3i5mnk2rvwvyfcgwxd4" > put_exp &&
167
test_cmp put_exp put_out
168
'
169
test/sharness/t0252-files-gc.sh
+2
-2
@@ -38,9 +38,9 @@ test_expect_success "gc okay after adding incomplete node -- prep" '
38
'
39
40
test_expect_success "gc okay after adding incomplete node" '
41
- ipfs object stat $ADIR_HASH &&
41
+ ipfs dag get $ADIR_HASH &&
42
ipfs repo gc &&
43
- ipfs object stat $ADIR_HASH
43
+ ipfs dag get $ADIR_HASH
44
'
45
46
test_expect_success "add directory with direct pin" '