Skip to content

Commit

Permalink
fix: MustGetChildren works at the node level
Browse files Browse the repository at this point in the history
Fixes #54 

`(Must)GetChildren` operations where running at the unixfs layer of abstraction, which doesn't work when you're trying to list the children block of a file that is split into multiple nodes.

Implement the operations at the ipld dag abstraction, meaning it's possible to list all the children blocks / CID in a file for example.
  • Loading branch information
laurentsenta committed May 23, 2023
2 parents 5f2bc9c + 9819adf commit c32f74d
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 29 deletions.
1 change: 1 addition & 0 deletions tooling/car/_fixtures/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dir-54
9 changes: 8 additions & 1 deletion tooling/car/_fixtures/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
all: dag.car
all: dag.car issue-54.car

dag.car:
npx ipfs-car pack --no-wrap ./dir --output ./dag.car

issue-54.car:
mkdir -p dir-54/sub1
echo "abc123" > dir-54/sub1/hello.txt
mkdir -p dir-54/sub2
echo "xyz456" > dir-54/sub2/hello.txt
ipfs dag export `ipfs add -Qr --chunker=size-5 dir-54` > ./issue-54.car
Binary file added tooling/car/_fixtures/issue-54.car
Binary file not shown.
63 changes: 63 additions & 0 deletions tooling/car/fixture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,66 @@ func TestGetNodes(t *testing.T) {
assert.Equal(t, "bafybeiaq6e55xratife7s5cmzjcmwy4adzzlk74sbdpfcq72gus6cweeeq", cids[2])
assert.Equal(t, "bafkreihdhgb5vyuqu7jssreyo3h567obewtqq37fi5hr2w4um5icacry7m", cids[3])
}

func TestIssue54MustGetChildren(t *testing.T) {
f := MustOpenUnixfsCar("./_fixtures/issue-54.car")

// › npx ipfs-car ls ./issue-54.car --verbose
// QmT5W42oo38Bi4mL2aktaMyqu7tqj7xWCuZhmoTfo7XtiU - .
// QmUBzv8HDDtnivUvPGkqBmkCeMJKeAWhUZtb5D8ouGnATZ - ./sub1
// QmZgfvZtoFdbJy4JmpPHc1NCXyA7Snim2L8e6zKspiUzhu 7 ./sub1/hello.txt
// QmVtAZGRHTCzSNt1vRgz1UESvcc57ebEcDYTaDJjVu1SrA - ./sub2
// Qmf4EqZZpFPcy6oKsc84dGS5EpPdXYZ1hq39Gemadu6hfW 7 ./sub2/hello.txt
cids := f.MustGetChildrenCids("sub1", "hello.txt")

// › ipfs dag get QmZgfvZtoFdbJy4JmpPHc1NCXyA7Snim2L8e6zKspiUzhu | jq
// {
// "Data": {
// "/": {
// "bytes": "CAIYByAFIAI"
// }
// },
// "Links": [
// {
// "Hash": {
// "/": "QmaATBg1yioWhYHhoA8XSUqD1Ya91KKCibWVD4USQXwaVZ"
// },
// "Name": "",
// "Tsize": 13
// },
// {
// "Hash": {
// "/": "QmdQEnYhrhgFKPCq5eKc7xb1k7rKyb3fGMitUPKvFAscVK"
// },
// "Name": "",
// "Tsize": 10
// }
// ]
// }
assert.Len(t, cids, 2)
assert.Equal(t, "QmaATBg1yioWhYHhoA8XSUqD1Ya91KKCibWVD4USQXwaVZ", cids[0])
assert.Equal(t, "QmdQEnYhrhgFKPCq5eKc7xb1k7rKyb3fGMitUPKvFAscVK", cids[1])

// › ipfs dag get 'Qmb7KRN5qCAwTYXAdTd5JHzXXQv3BDRJQhcEuMJzdiGix6' | jq
// {
// "Data": {
// "/": {
// "bytes": "CAE"
// }
// },
// "Links": [
// {
// "Hash": {
// "/": "QmZgfvZtoFdbJy4JmpPHc1NCXyA7Snim2L8e6zKspiUzhu"
// },
// "Name": "hello.txt",
// "Tsize": 117
// }
// ]
// }
cids = f.MustGetChildrenCids("sub1")
assert.Len(t, cids, 3)
assert.Equal(t, "QmZgfvZtoFdbJy4JmpPHc1NCXyA7Snim2L8e6zKspiUzhu", cids[0])
assert.Equal(t, "QmaATBg1yioWhYHhoA8XSUqD1Ya91KKCibWVD4USQXwaVZ", cids[1])
assert.Equal(t, "QmdQEnYhrhgFKPCq5eKc7xb1k7rKyb3fGMitUPKvFAscVK", cids[2])
}
42 changes: 14 additions & 28 deletions tooling/car/unixfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"fmt"
"os"
"path"
"sort"
"strings"

"github.com/ipfs/boxo/blockservice"
Expand Down Expand Up @@ -100,33 +99,26 @@ func (d *UnixfsDag) getNode(names ...string) (format.Node, error) {
return d.node, nil
}

func (d *UnixfsDag) listChildren(names ...string) ([][]string, error) {
func (d *UnixfsDag) listChildren(names ...string) ([]*FixtureNode, error) {
node, err := d.getNode(names...)
if err != nil {
return nil, err
}

result := [][]string{}
result := []*FixtureNode{}
var recursive func(node format.Node) error

var recursive func(format.Node, []string) error
recursive = func(node format.Node) error {
result = append(result, &FixtureNode{node: node, dsvc: d.dsvc})
links := node.Links()

recursive = func(node format.Node, path []string) error {
result = append(result, path)

links, err := d.loadLinks(node)
if err != nil {
fmt.Println(err)
}
// ignore the error: we might descend through files.

var names []string
for name := range links {
names = append(names, name)
}
sort.Strings(names)
for _, link := range links {
node, err := link.GetNode(context.Background(), d.dsvc)
if err != nil {
return err
}

for _, name := range names {
err := recursive(links[name].mustGetNode(), append(path, name))
err = recursive(node)
if err != nil {
return err
}
Expand All @@ -135,7 +127,7 @@ func (d *UnixfsDag) listChildren(names ...string) ([][]string, error) {
return nil
}

err = recursive(node, names)
err = recursive(node)
if err != nil {
return nil, err
}
Expand All @@ -156,16 +148,10 @@ func (d *UnixfsDag) MustGetNode(names ...string) *FixtureNode {
}

func (d *UnixfsDag) MustGetChildren(names ...string) [](*FixtureNode) {
paths, err := d.listChildren(names...)
nodes, err := d.listChildren(names...)
if err != nil {
panic(err)
}

var nodes [](*FixtureNode)
for _, path := range paths {
nodes = append(nodes, d.MustGetNode(path...))
}

return nodes
}

Expand Down

0 comments on commit c32f74d

Please sign in to comment.