Skip to content
This repository was archived by the owner on Sep 28, 2021. It is now read-only.

Commit 25edfbc

Browse files
achingbrainvasco-santos
authored andcommitted
feat: load files/dirs from hamt shards (#19)
Use the HAMT support and IPFS overlay build in to the mfs related files commands to enable loading files from HAMT shards.
1 parent 9a88d61 commit 25edfbc

File tree

2 files changed

+53
-116
lines changed

2 files changed

+53
-116
lines changed

src/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const response = (ipfsNode, ipfsPath) => {
2828
return new Promise((resolve, reject) => {
2929
// switch case with true feels so wrong.
3030
switch (true) {
31-
case (errorString === 'Error: This dag node is a directory'):
31+
case (errorString.includes('dag node is a directory')):
3232
resolver.directory(node, path, error.cid)
3333
.then((content) => {
3434
// dir render

src/resolver.js

+52-115
Original file line numberDiff line numberDiff line change
@@ -2,142 +2,79 @@
22

33
const mh = require('multihashes')
44
const promisify = require('promisify-es6')
5-
const reduce = require('async/reduce')
65
const CID = require('cids')
7-
const Unixfs = require('ipfs-unixfs')
86
const debug = require('debug')
9-
const log = debug('ipfs:http:response:resolver')
10-
7+
const tryEach = require('async/tryEach')
8+
const waterfall = require('async/waterfall')
9+
const log = debug('jsipfs:http:response:resolver')
10+
log.error = debug('jsipfs:http:response:resolver:error')
1111
const dirView = require('./dir-view')
12-
const pathUtil = require('./utils/path')
1312

14-
function getIndexFiles (links) {
15-
const INDEX_HTML_FILES = [
16-
'index.html',
17-
'index.htm',
18-
'index.shtml'
19-
]
20-
// directory
21-
let indexes = links.filter((link) => INDEX_HTML_FILES.indexOf(link.Name) !== -1)
22-
if (indexes.length) {
23-
return indexes
24-
}
25-
// hamt-sharded-directory uses a 2 char prefix
26-
return links.filter((link) => {
27-
return link.Name.length > 2 && INDEX_HTML_FILES.indexOf(link.Name.substring(2)) !== -1
28-
})
13+
const INDEX_HTML_FILES = [
14+
'index.html',
15+
'index.htm',
16+
'index.shtml'
17+
]
18+
19+
const findIndexFile = (ipfs, path, callback) => {
20+
return tryEach(INDEX_HTML_FILES.map(file => {
21+
return (cb) => {
22+
waterfall([
23+
(cb) => ipfs.files.stat(`${path}/${file}`, cb),
24+
(stats, cb) => cb(null, {
25+
name: file,
26+
cid: new CID(stats.hash)
27+
})
28+
], cb)
29+
}
30+
}), callback)
2931
}
3032

3133
const directory = promisify((ipfs, path, cid, callback) => {
32-
cid = new CID(cid)
33-
34-
ipfs.object.get(cid.buffer, (err, dagNode) => {
34+
// Test if it is a Website
35+
findIndexFile(ipfs, path, (err, res) => {
3536
if (err) {
36-
return callback(err)
37-
}
37+
if (err.message.includes('does not exist')) {
38+
// not a website, just show a directory listing
39+
return ipfs.dag.get(cid, (err, result) => {
40+
if (err) {
41+
return callback(err)
42+
}
3843

39-
// Test if it is a Website
40-
const indexFiles = getIndexFiles(dagNode.Links)
44+
return callback(null, dirView.render(path, result.value.Links))
45+
})
46+
}
4147

42-
if (indexFiles.length) {
43-
return callback(null, indexFiles)
48+
return callback(err)
4449
}
4550

46-
return callback(null, dirView.render(path, dagNode.Links))
51+
callback(err, [{
52+
Name: res.name
53+
}])
4754
})
4855
})
4956

5057
const cid = promisify((ipfs, path, callback) => {
51-
const parts = pathUtil.cidArray(path)
52-
let firstCid = parts.shift()
53-
let currentCid
54-
55-
// TODO: replace below with ipfs.resolve(path, {recursive: true})
56-
// (requires changes to js-ipfs/js-ipfs-api)
57-
58-
reduce(
59-
parts,
60-
firstCid,
61-
(memo, item, next) => {
62-
try {
63-
currentCid = new CID(memo)
64-
} catch (err) {
65-
return next(err)
66-
}
67-
68-
log('memo: ', memo)
69-
log('item: ', item)
70-
71-
ipfs.dag.get(currentCid, (err, result) => {
72-
if (err) {
73-
return next(err)
74-
}
75-
76-
const dagNode = result.value
77-
// find multihash/cid of requested named-file in current dagNode's links
78-
let cidOfNextFile
79-
const nextFileName = item
80-
81-
try {
82-
for (let link of dagNode.Links) {
83-
if (link.Name === nextFileName) {
84-
cidOfNextFile = link.Hash
85-
break
86-
}
87-
}
88-
} catch (err) {
89-
return next(err)
90-
}
91-
92-
if (!cidOfNextFile) {
93-
const missingLinkErr = new Error(`no link named "${nextFileName}" under ${memo}`)
94-
missingLinkErr.parentDagNode = memo
95-
missingLinkErr.missingLinkName = nextFileName
96-
return next(missingLinkErr)
97-
}
98-
99-
next(null, cidOfNextFile)
100-
})
101-
}, (err, cid) => {
102-
if (err) {
103-
return callback(err)
104-
}
105-
106-
try {
107-
cid = new CID(cid)
108-
} catch (err) {
109-
return callback(err)
110-
}
58+
ipfs.files.stat(path, (err, stats) => {
59+
if (err) {
60+
return callback(err)
61+
}
11162

112-
if (cid.codec === 'raw') {
113-
// no need for additional lookup, its raw data
114-
callback(null, { cid })
115-
}
63+
const cid = new CID(stats.hash)
11664

117-
ipfs.dag.get(cid, (err, dagResult) => {
118-
if (err) {
119-
return callback(err)
120-
}
65+
if (stats.type.includes('directory')) {
66+
const err = new Error('This dag node is a directory')
67+
err.cid = cid
68+
err.fileName = stats.name
69+
err.dagDirType = stats.type
12170

122-
try {
123-
let dagDataObj = Unixfs.unmarshal(dagResult.value.Data)
124-
// There are at least two types of directories:
125-
// - "directory"
126-
// - "hamt-sharded-directory" (example: QmT5NvUtoM5nWFfrQdVrFtvGfKFmG7AHE8P34isapyhCxX)
127-
if (dagDataObj.type === 'directory' || dagDataObj.type === 'hamt-sharded-directory') {
128-
let isDirErr = new Error('This dag node is a directory')
129-
// store memo of last multihash so it can be used by directory
130-
isDirErr.cid = isDirErr.fileName = cid
131-
isDirErr.dagDirType = dagDataObj.type
132-
return callback(isDirErr)
133-
}
134-
} catch (err) {
135-
return callback(err)
136-
}
71+
return callback(err)
72+
}
13773

138-
callback(null, { cid })
139-
})
74+
callback(err, {
75+
cid
14076
})
77+
})
14178
})
14279

14380
const multihash = promisify((ipfs, path, callback) => {

0 commit comments

Comments
 (0)