1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-05-17 23:16:11 +08:00
Files
kubo/core/coreapi/object.go
2024-03-22 09:32:30 +01:00

155 lines
3.6 KiB
Go

package coreapi
import (
"context"
dag "github.com/ipfs/boxo/ipld/merkledag"
"github.com/ipfs/boxo/ipld/merkledag/dagutils"
ft "github.com/ipfs/boxo/ipld/unixfs"
"github.com/ipfs/boxo/path"
coreiface "github.com/ipfs/kubo/core/coreiface"
caopts "github.com/ipfs/kubo/core/coreiface/options"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"github.com/ipfs/kubo/tracing"
)
type ObjectAPI CoreAPI
type Link struct {
Name, Hash string
Size uint64
}
type Node struct {
Links []Link
Data string
}
func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string, child path.Path, opts ...caopts.ObjectAddLinkOption) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "AddLink", trace.WithAttributes(
attribute.String("base", base.String()),
attribute.String("name", name),
attribute.String("child", child.String()),
))
defer span.End()
options, err := caopts.ObjectAddLinkOptions(opts...)
if err != nil {
return path.ImmutablePath{}, err
}
span.SetAttributes(attribute.Bool("create", options.Create))
baseNd, err := api.core().ResolveNode(ctx, base)
if err != nil {
return path.ImmutablePath{}, err
}
childNd, err := api.core().ResolveNode(ctx, child)
if err != nil {
return path.ImmutablePath{}, err
}
basePb, ok := baseNd.(*dag.ProtoNode)
if !ok {
return path.ImmutablePath{}, dag.ErrNotProtobuf
}
var createfunc func() *dag.ProtoNode
if options.Create {
createfunc = ft.EmptyDirNode
}
e := dagutils.NewDagEditor(basePb, api.dag)
err = e.InsertNodeAtPath(ctx, name, childNd, createfunc)
if err != nil {
return path.ImmutablePath{}, err
}
nnode, err := e.Finalize(ctx, api.dag)
if err != nil {
return path.ImmutablePath{}, err
}
return path.FromCid(nnode.Cid()), nil
}
func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "RmLink", trace.WithAttributes(
attribute.String("base", base.String()),
attribute.String("link", link)),
)
defer span.End()
baseNd, err := api.core().ResolveNode(ctx, base)
if err != nil {
return path.ImmutablePath{}, err
}
basePb, ok := baseNd.(*dag.ProtoNode)
if !ok {
return path.ImmutablePath{}, dag.ErrNotProtobuf
}
e := dagutils.NewDagEditor(basePb, api.dag)
err = e.RmLink(ctx, link)
if err != nil {
return path.ImmutablePath{}, err
}
nnode, err := e.Finalize(ctx, api.dag)
if err != nil {
return path.ImmutablePath{}, err
}
return path.FromCid(nnode.Cid()), nil
}
func (api *ObjectAPI) Diff(ctx context.Context, before path.Path, after path.Path) ([]coreiface.ObjectChange, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Diff", trace.WithAttributes(
attribute.String("before", before.String()),
attribute.String("after", after.String()),
))
defer span.End()
beforeNd, err := api.core().ResolveNode(ctx, before)
if err != nil {
return nil, err
}
afterNd, err := api.core().ResolveNode(ctx, after)
if err != nil {
return nil, err
}
changes, err := dagutils.Diff(ctx, api.dag, beforeNd, afterNd)
if err != nil {
return nil, err
}
out := make([]coreiface.ObjectChange, len(changes))
for i, change := range changes {
out[i] = coreiface.ObjectChange{
Type: coreiface.ChangeType(change.Type),
Path: change.Path,
}
if change.Before.Defined() {
out[i].Before = path.FromCid(change.Before)
}
if change.After.Defined() {
out[i].After = path.FromCid(change.After)
}
}
return out, nil
}
func (api *ObjectAPI) core() coreiface.CoreAPI {
return (*CoreAPI)(api)
}