@cryptotaxi247 / kubo / commits / 9047fed8d

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" '