diff --git a/path/resolver/resolver.go b/path/resolver/resolver.go index 05341655a..af6b8628c 100644 --- a/path/resolver/resolver.go +++ b/path/resolver/resolver.go @@ -69,25 +69,46 @@ func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath path.Path) (ipld } for len(p) > 0 { - val, rest, err := nd.Resolve(p) + lnk, rest, err := r.ResolveOnce(ctx, r.DAG, nd, p) + + // Note: have to drop the error here as `ResolveOnce` doesn't handle 'leaf' + // paths (so e.g. for `echo '{"foo":123}' | ipfs dag put` we wouldn't be + // able to resolve `zdpu[...]/foo`) + if lnk == nil { + break + } + if err != nil { return nil, nil, err } - switch val := val.(type) { - case *ipld.Link: - next, err := val.GetNode(ctx, r.DAG) - if err != nil { - return nil, nil, err - } - nd = next - p = rest - default: - return nd, p, nil + next, err := lnk.GetNode(ctx, r.DAG) + if err != nil { + return nil, nil, err } + nd = next + p = rest } - return nd, nil, nil + if len(p) == 0 { + return nd, nil, nil + } + + // Confirm the path exists within the object + val, rest, err := nd.Resolve(p) + if err != nil { + return nil, nil, err + } + + if len(rest) > 0 { + return nil, nil, errors.New("path failed to resolve fully") + } + switch val.(type) { + case *ipld.Link: + return nil, nil, errors.New("inconsistent ResolveOnce / nd.Resolve") + default: + return nd, p, nil + } } // ResolvePath fetches the node for given path. It returns the last item diff --git a/test/sharness/t0260-sharding.sh b/test/sharness/t0260-sharding.sh index 63f797aba..01fc447f4 100755 --- a/test/sharness/t0260-sharding.sh +++ b/test/sharness/t0260-sharding.sh @@ -76,6 +76,15 @@ test_expect_success "'ipfs ls --resolve-type=false' admits missing block" ' test_cmp sharded_out missing_out ' +test_launch_ipfs_daemon + +test_expect_success "gateway can resolve sharded dirs" ' + echo 100 > expected && + curl -sfo actual "http://127.0.0.1:$GWAY_PORT/ipfs/$SHARDED/file100" && + test_cmp expected actual +' + +test_kill_ipfs_daemon test_add_large_dir_v1() { exphash="$1"