/ core / coreapi / path.go
path.go
 1  package coreapi
 2  
 3  import (
 4  	"context"
 5  	"errors"
 6  	"fmt"
 7  
 8  	"github.com/ipfs/boxo/namesys"
 9  	"github.com/ipfs/kubo/tracing"
10  
11  	"go.opentelemetry.io/otel/attribute"
12  	"go.opentelemetry.io/otel/trace"
13  
14  	"github.com/ipfs/boxo/path"
15  	ipfspathresolver "github.com/ipfs/boxo/path/resolver"
16  	ipld "github.com/ipfs/go-ipld-format"
17  	coreiface "github.com/ipfs/kubo/core/coreiface"
18  )
19  
20  // ResolveNode resolves the path `p` using Unixfs resolver, gets and returns the
21  // resolved Node.
22  func (api *CoreAPI) ResolveNode(ctx context.Context, p path.Path) (ipld.Node, error) {
23  	ctx, span := tracing.Span(ctx, "CoreAPI", "ResolveNode", trace.WithAttributes(attribute.String("path", p.String())))
24  	defer span.End()
25  
26  	rp, _, err := api.ResolvePath(ctx, p)
27  	if err != nil {
28  		return nil, err
29  	}
30  
31  	node, err := api.dag.Get(ctx, rp.RootCid())
32  	if err != nil {
33  		return nil, err
34  	}
35  	return node, nil
36  }
37  
38  // ResolvePath resolves the path `p` using Unixfs resolver, returns the
39  // resolved path.
40  func (api *CoreAPI) ResolvePath(ctx context.Context, p path.Path) (path.ImmutablePath, []string, error) {
41  	ctx, span := tracing.Span(ctx, "CoreAPI", "ResolvePath", trace.WithAttributes(attribute.String("path", p.String())))
42  	defer span.End()
43  
44  	res, err := namesys.Resolve(ctx, api.namesys, p)
45  	if errors.Is(err, namesys.ErrNoNamesys) {
46  		return path.ImmutablePath{}, nil, coreiface.ErrOffline
47  	} else if err != nil {
48  		return path.ImmutablePath{}, nil, err
49  	}
50  	p = res.Path
51  
52  	var resolver ipfspathresolver.Resolver
53  	switch p.Namespace() {
54  	case path.IPLDNamespace:
55  		resolver = api.ipldPathResolver
56  	case path.IPFSNamespace:
57  		resolver = api.unixFSPathResolver
58  	default:
59  		return path.ImmutablePath{}, nil, fmt.Errorf("unsupported path namespace: %s", p.Namespace())
60  	}
61  
62  	imPath, err := path.NewImmutablePath(p)
63  	if err != nil {
64  		return path.ImmutablePath{}, nil, err
65  	}
66  
67  	node, remainder, err := resolver.ResolveToLastNode(ctx, imPath)
68  	if err != nil {
69  		return path.ImmutablePath{}, nil, err
70  	}
71  
72  	segments := []string{p.Namespace(), node.String()}
73  	segments = append(segments, remainder...)
74  
75  	p, err = path.NewPathFromSegments(segments...)
76  	if err != nil {
77  		return path.ImmutablePath{}, nil, err
78  	}
79  
80  	imPath, err = path.NewImmutablePath(p)
81  	if err != nil {
82  		return path.ImmutablePath{}, nil, err
83  	}
84  
85  	return imPath, remainder, nil
86  }