object.go
1 package coreapi 2 3 import ( 4 "context" 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" 10 coreiface "github.com/ipfs/kubo/core/coreiface" 11 caopts "github.com/ipfs/kubo/core/coreiface/options" 12 "go.opentelemetry.io/otel/attribute" 13 "go.opentelemetry.io/otel/trace" 14 15 "github.com/ipfs/kubo/tracing" 16 ) 17 18 type ObjectAPI CoreAPI 19 20 type Link struct { 21 Name, Hash string 22 Size uint64 23 } 24 25 type Node struct { 26 Links []Link 27 Data string 28 } 29 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()), 33 attribute.String("name", name), 34 attribute.String("child", child.String()), 35 )) 36 defer span.End() 37 38 options, err := caopts.ObjectAddLinkOptions(opts...) 39 if err != nil { 40 return path.ImmutablePath{}, err 41 } 42 span.SetAttributes(attribute.Bool("create", options.Create)) 43 44 baseNd, err := api.core().ResolveNode(ctx, base) 45 if err != nil { 46 return path.ImmutablePath{}, err 47 } 48 49 childNd, err := api.core().ResolveNode(ctx, child) 50 if err != nil { 51 return path.ImmutablePath{}, err 52 } 53 54 basePb, ok := baseNd.(*dag.ProtoNode) 55 if !ok { 56 return path.ImmutablePath{}, dag.ErrNotProtobuf 57 } 58 59 var createfunc func() *dag.ProtoNode 60 if options.Create { 61 createfunc = ft.EmptyDirNode 62 } 63 64 e := dagutils.NewDagEditor(basePb, api.dag) 65 66 err = e.InsertNodeAtPath(ctx, name, childNd, createfunc) 67 if err != nil { 68 return path.ImmutablePath{}, err 69 } 70 71 nnode, err := e.Finalize(ctx, api.dag) 72 if err != nil { 73 return path.ImmutablePath{}, err 74 } 75 76 return path.FromCid(nnode.Cid()), nil 77 } 78 79 func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (path.ImmutablePath, error) { 80 ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "RmLink", trace.WithAttributes( 81 attribute.String("base", base.String()), 82 attribute.String("link", link)), 83 ) 84 defer span.End() 85 86 baseNd, err := api.core().ResolveNode(ctx, base) 87 if err != nil { 88 return path.ImmutablePath{}, err 89 } 90 91 basePb, ok := baseNd.(*dag.ProtoNode) 92 if !ok { 93 return path.ImmutablePath{}, dag.ErrNotProtobuf 94 } 95 96 e := dagutils.NewDagEditor(basePb, api.dag) 97 98 err = e.RmLink(ctx, link) 99 if err != nil { 100 return path.ImmutablePath{}, err 101 } 102 103 nnode, err := e.Finalize(ctx, api.dag) 104 if err != nil { 105 return path.ImmutablePath{}, err 106 } 107 108 return path.FromCid(nnode.Cid()), nil 109 } 110 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()), 114 attribute.String("after", after.String()), 115 )) 116 defer span.End() 117 118 beforeNd, err := api.core().ResolveNode(ctx, before) 119 if err != nil { 120 return nil, err 121 } 122 123 afterNd, err := api.core().ResolveNode(ctx, after) 124 if err != nil { 125 return nil, err 126 } 127 128 changes, err := dagutils.Diff(ctx, api.dag, beforeNd, afterNd) 129 if err != nil { 130 return nil, err 131 } 132 133 out := make([]coreiface.ObjectChange, len(changes)) 134 for i, change := range changes { 135 out[i] = coreiface.ObjectChange{ 136 Type: coreiface.ChangeType(change.Type), 137 Path: change.Path, 138 } 139 140 if change.Before.Defined() { 141 out[i].Before = path.FromCid(change.Before) 142 } 143 144 if change.After.Defined() { 145 out[i].After = path.FromCid(change.After) 146 } 147 } 148 149 return out, nil 150 } 151 152 func (api *ObjectAPI) core() coreiface.CoreAPI { 153 return (*CoreAPI)(api) 154 }