Skip to content
This repository was archived by the owner on Aug 12, 2020. It is now read-only.

Commit 7345240

Browse files
committed
big exporter overhaul: centralized dag reslving inside internal resolver stream
1 parent e0b9da3 commit 7345240

File tree

10 files changed

+119
-81
lines changed

10 files changed

+119
-81
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
"pull-batch": "^1.0.0",
7171
"pull-block": "1.2.0",
7272
"pull-cat": "^1.1.11",
73-
"pull-defer": "~0.2.2",
7473
"pull-pair": "^1.1.0",
7574
"pull-paramap": "^1.2.2",
7675
"pull-pause": "0.0.1",

src/exporter/dir-flat.js

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
'use strict'
22

33
const pull = require('pull-stream')
4-
const paramap = require('pull-paramap')
54
const CID = require('cids')
65
const cat = require('pull-cat')
76

87
// Logic to export a unixfs directory.
98
module.exports = dirExporter
109

11-
function dirExporter (node, name, pathRest, ipldResolver, resolve, parent) {
10+
function dirExporter (node, name, pathRest, resolve) {
1211
const accepts = pathRest[0]
1312

1413
const dir = {
@@ -20,19 +19,13 @@ function dirExporter (node, name, pathRest, ipldResolver, resolve, parent) {
2019
pull(
2120
pull.values(node.links),
2221
pull.map((link) => ({
23-
linkName: link.name,
2422
path: name + '/' + link.name,
25-
hash: link.multihash
23+
multihash: link.multihash,
24+
linkName: link.name,
25+
pathRest: pathRest.slice(1)
2626
})),
2727
pull.filter((item) => accepts === undefined || item.linkName === accepts),
28-
paramap((item, cb) => ipldResolver.get(new CID(item.hash), (err, n) => {
29-
if (err) {
30-
return cb(err)
31-
}
32-
33-
cb(null, resolve(n.value, accepts || item.path, pathRest, ipldResolver, name, parent))
34-
})),
35-
pull.flatten()
28+
resolve
3629
)
3730
]
3831

@@ -41,7 +34,5 @@ function dirExporter (node, name, pathRest, ipldResolver, resolve, parent) {
4134
streams.unshift(pull.values([dir]))
4235
}
4336

44-
pathRest.shift()
45-
4637
return cat(streams)
4738
}

src/exporter/dir-hamt-sharded.js

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
'use strict'
22

33
const pull = require('pull-stream')
4-
const paramap = require('pull-paramap')
54
const CID = require('cids')
65
const cat = require('pull-cat')
76
const cleanHash = require('./clean-multihash')
87

98
// Logic to export a unixfs directory.
109
module.exports = shardedDirExporter
1110

12-
function shardedDirExporter (node, name, pathRest, ipldResolver, resolve, parent) {
11+
function shardedDirExporter (node, name, pathRest, resolve, dag, parent) {
1312
let dir
1413
if (!parent || parent.path !== name) {
1514
dir = [{
@@ -37,29 +36,16 @@ function shardedDirExporter (node, name, pathRest, ipldResolver, resolve, parent
3736
fromPathRest: fromPathRest,
3837
name: p,
3938
path: pp,
40-
hash: link.multihash,
41-
pathRest: p ? pathRest.slice(1) : pathRest
39+
multihash: link.multihash,
40+
pathRest: p ? pathRest.slice(1) : pathRest,
41+
parent: (dir && dir[0]) || parent
4242
}
4343
} else {
4444
return ''
4545
}
4646
}),
4747
pull.filter(Boolean),
48-
paramap((item, cb) => ipldResolver.get(new CID(item.hash), (err, n) => {
49-
if (err) {
50-
return cb(err)
51-
}
52-
53-
cb(
54-
null,
55-
resolve(
56-
n.value,
57-
item.fromPathRest ? item.name : item.path,
58-
item.pathRest,
59-
ipldResolver,
60-
(dir && dir[0]) || parent))
61-
})),
62-
pull.flatten()
48+
resolve
6349
)
6450
]
6551

src/exporter/file.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const pull = require('pull-stream')
77
const paramap = require('pull-paramap')
88

99
// Logic to export a single (possibly chunked) unixfs file.
10-
module.exports = (node, name, pathRest, ipldResolver) => {
10+
module.exports = (node, name, pathRest, resolve, dag) => {
1111
function getData (node) {
1212
try {
1313
const file = UnixFS.unmarshal(node.data)
@@ -20,12 +20,12 @@ module.exports = (node, name, pathRest, ipldResolver) => {
2020
function visitor (node) {
2121
return pull(
2222
pull.values(node.links),
23-
paramap((link, cb) => ipldResolver.get(new CID(link.multihash), cb)),
23+
paramap((link, cb) => dag.get(new CID(link.multihash), cb)),
2424
pull.map((result) => result.value)
2525
)
2626
}
2727

28-
const accepts = pathRest.shift()
28+
const accepts = pathRest[0]
2929

3030
if (accepts !== undefined && accepts !== name) {
3131
return pull.empty()

src/exporter/index.js

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
const pull = require('pull-stream')
44
const CID = require('cids')
5-
const pullDefer = require('pull-defer')
5+
const b58Encode = require('bs58').encode
66

7-
const resolve = require('./resolve').resolve
7+
const createResolver = require('./resolve').createResolver
88

99
function pathBaseAndRest (path) {
1010
// Buffer -> raw multihash or CID in buffer
@@ -36,28 +36,60 @@ function pathBaseAndRest (path) {
3636
}
3737
}
3838

39-
module.exports = (path, dag) => {
39+
const defaultOptions = {
40+
recurse: true
41+
}
42+
43+
module.exports = (path, dag, _options) => {
44+
45+
const options = Object.assign({}, defaultOptions, _options)
46+
47+
let dPath
4048
try {
41-
path = pathBaseAndRest(path)
49+
dPath = pathBaseAndRest(path)
4250
} catch (err) {
4351
return pull.error(err)
4452
}
4553

46-
const d = pullDefer.source()
47-
48-
const cid = new CID(path.base)
54+
return pull(
55+
pull.values([{
56+
multihash: new CID(dPath.base),
57+
name: dPath.base,
58+
path: dPath.base,
59+
pathRest: dPath.rest
60+
}]),
61+
createResolver(dag, options),
62+
pull.map((node) => ({
63+
path: finalPathFor(node),
64+
size: node.size,
65+
hash: node.hash,
66+
content: node.content
67+
}))
68+
)
4969

50-
dag.get(cid, (err, node) => {
51-
if (err) {
52-
return pull.error(err)
70+
function finalPathFor(node) {
71+
if (!dPath.rest.length) {
72+
return node.path
5373
}
54-
d.resolve(pull.values([node]))
55-
})
5674

57-
return pull(
58-
d,
59-
pull.map((result) => result.value),
60-
pull.map((node) => resolve(node, path.base, path.rest, dag)),
61-
pull.flatten()
62-
)
75+
const cutElements = [dPath.base].concat(dPath.rest.slice(0, dPath.rest.length - 1))
76+
const lengthToCut = join(cutElements).length
77+
let retPath = node.path.substring(lengthToCut)
78+
if (retPath.charAt(0) === '/') {
79+
retPath = retPath.substring(1)
80+
}
81+
if (!retPath) {
82+
retPath = dPath.rest[dPath.rest.length - 1] || dPath.base
83+
}
84+
return retPath
85+
}
6386
}
87+
88+
function join(paths) {
89+
return paths.reduce((acc, path) => {
90+
if (acc.length) {
91+
acc += '/'
92+
}
93+
return acc + path
94+
}, '')
95+
}

src/exporter/object.js

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,26 @@
22

33
const CID = require('cids')
44
const pull = require('pull-stream')
5-
const pullDefer = require('pull-defer')
65

7-
module.exports = (node, name, pathRest, ipldResolver, resolve) => {
6+
module.exports = (node, name, pathRest, resolve, dag, parent) => {
87
let newNode
98
if (pathRest.length) {
10-
const pathElem = pathRest.shift()
9+
const pathElem = pathRest[0]
1110
newNode = node[pathElem]
1211
const newName = name + '/' + pathElem
13-
if (CID.isCID(newNode)) {
14-
const d = pullDefer.source()
15-
ipldResolver.get(sanitizeCID(newNode), (err, newNode) => {
16-
if (err) {
17-
d.resolve(pull.error(err))
18-
} else {
19-
d.resolve(resolve(newNode.value, newName, pathRest, ipldResolver, node))
20-
}
21-
})
22-
return d
23-
} else if (newNode !== undefined) {
24-
return resolve(newNode, newName, pathRest, ipldResolver, node)
25-
} else {
12+
if (!newNode) {
2613
return pull.error('not found')
2714
}
15+
const isCID = CID.isCID(newNode)
16+
return pull(
17+
pull.values([{
18+
path: newName,
19+
pathRest: pathRest.slice(1),
20+
multihash: isCID && newNode,
21+
object: !isCID && newNode,
22+
parent: parent
23+
}]),
24+
resolve)
2825
} else {
2926
return pull.error(new Error('invalid node type'))
3027
}

src/exporter/resolve.js

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
const UnixFS = require('ipfs-unixfs')
44
const pull = require('pull-stream')
5+
const paramap = require('pull-paramap')
6+
const CID = require('cids')
57

68
const resolvers = {
79
directory: require('./dir-flat'),
@@ -11,17 +13,44 @@ const resolvers = {
1113
}
1214

1315
module.exports = Object.assign({
14-
resolve: resolve,
16+
createResolver: createResolver,
1517
typeOf: typeOf
1618
}, resolvers)
1719

18-
function resolve (node, hash, pathRest, ipldResolver, parentNode) {
19-
const type = typeOf(node)
20-
const resolver = resolvers[type]
21-
if (!resolver) {
22-
return pull.error(new Error('Unkown node type ' + type))
20+
function createResolver (dag, options, depth, parent) {
21+
if (! depth) {
22+
depth = 0
23+
}
24+
25+
if (!options.recurse && depth > 0) {
26+
return pull.map(identity)
27+
}
28+
29+
return pull(
30+
paramap((item, cb) => {
31+
if (item.object) {
32+
return cb(null, resolve(item.object, item.path, item.pathRest, dag, item.parent || parent))
33+
}
34+
dag.get(new CID(item.multihash), (err, node) => {
35+
if (err) {
36+
return cb(err)
37+
}
38+
const name = item.fromPathRest ? item.name : item.path
39+
cb(null, resolve(node.value, name, item.pathRest, dag, item.parent || parent))
40+
})
41+
}),
42+
pull.flatten()
43+
)
44+
45+
function resolve (node, hash, pathRest, parentNode) {
46+
const type = typeOf(node)
47+
const nodeResolver = resolvers[type]
48+
if (!nodeResolver) {
49+
return pull.error(new Error('Unkown node type ' + type))
50+
}
51+
const resolveDeep = createResolver(dag, options, depth + 1, node)
52+
return nodeResolver(node, hash, pathRest, resolveDeep, dag, parentNode)
2353
}
24-
return resolver(node, hash, pathRest, ipldResolver, resolve, parentNode)
2554
}
2655

2756
function typeOf (node) {
@@ -31,3 +60,7 @@ function typeOf (node) {
3160
return 'object'
3261
}
3362
}
63+
64+
function identity (o) {
65+
return o
66+
}

src/importer/tree-builder.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ function createTreeBuilder (ipldResolver, _options) {
9191
// ---- Add to tree
9292

9393
function addToTree (elem, callback) {
94-
const pathElems = elem.path.split('/').filter(notEmpty)
94+
const pathElems = (elem.path || '').split('/').filter(notEmpty)
9595
let parent = tree
9696
const lastIndex = pathElems.length - 1
9797

test/exporter-subtree.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const exporter = unixFSEngine.exporter
1616
const smallFile = loadFixture(__dirname, 'fixtures/200Bytes.txt')
1717

1818
module.exports = (repo) => {
19-
describe('exporter', function () {
19+
describe('exporter subtree', () => {
2020
this.timeout(10 * 1000)
2121

2222
let ipldResolver

test/exporter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ module.exports = (repo) => {
117117
pull(
118118
exporter(hash, ipldResolver),
119119
pull.collect((err, files) => {
120-
files.forEach(file => expect(file).to.have.property('hash'))
121120
expect(err).to.not.exist()
121+
files.forEach(file => expect(file).to.have.property('hash'))
122122

123123
expect(
124124
files.map((file) => file.path)

0 commit comments

Comments
 (0)