diff --git a/src/index.js b/src/index.js index 324de96..d3ef2e2 100644 --- a/src/index.js +++ b/src/index.js @@ -61,7 +61,7 @@ module.exports = (path, dag, options) => { pull.values([{ multihash: cid.buffer, name: dPath.base, - path: dPath.base, + path: `${dPath.base}${dPath.rest.length ? `/${dPath.rest.join('/')}` : ''}`, pathRest: dPath.rest, depth: 0 }]), diff --git a/src/resolve.js b/src/resolve.js index a6c1930..b285005 100644 --- a/src/resolve.js +++ b/src/resolve.js @@ -40,10 +40,23 @@ function createResolver (dag, options, depth, parent) { const cid = new CID(item.multihash) - waterfall([ - (done) => dag.get(cid, done), - (node, done) => done(null, resolveItem(cid, node.value, item, options)) - ], cb) + dag.get(cid, item.pathRest.join('/'), (err, result) => { + if (err) { + if (err.message.includes('path not available')) { + return cb() + } + + return cb(err) + } + + const remainder = toPathComponents(result.remainderPath) + + item.name = toPathComponents(item.path).pop() + item.pathRest = remainder + item.multihash = result.cid.buffer + + cb(null, resolveItem(result.cid, result.value, item, options)) + }) }), pull.flatten(), pull.filter(Boolean), @@ -99,3 +112,11 @@ function typeOf (node) { function identity (o) { return o } + +const toPathComponents = (path = '') => { + // split on / unless escaped with \ + return (path + .trim() + .match(/([^\\\][^/]|\\\/)+/g) || []) + .filter(Boolean) +} diff --git a/test/exporter-subtree.spec.js b/test/exporter-subtree.spec.js index ddcdcab..707a0b3 100644 --- a/test/exporter-subtree.spec.js +++ b/test/exporter-subtree.spec.js @@ -43,17 +43,24 @@ describe('exporter subtree', () => { importer(ipld), pull.collect(cb) ), - (files, cb) => cb(null, files.pop().multihash), - (buf, cb) => cb(null, new CID(buf)), - (cid, cb) => pull( - exporter(`${cid.toBaseEncodedString()}/level-1/200Bytes.txt`, ipld), - pull.collect((err, files) => cb(err, { cid, files })) + (files, cb) => cb(null, [ + files[1].multihash, + files[3].multihash + ]), + ([ targetFileCidBuf, containingFolderCidBuf ], cb) => cb(null, [ + new CID(targetFileCidBuf), + new CID(containingFolderCidBuf) + ]), + ([ targetFileCid, containingFolderCid ], cb) => pull( + exporter(`${containingFolderCid.toBaseEncodedString()}/level-1/200Bytes.txt`, ipld), + pull.collect((err, files) => cb(err, { targetFileCid, containingFolderCid, files })) ), - ({ cid, files }, cb) => { + ({ targetFileCid, containingFolderCid, files }, cb) => { files.forEach(file => expect(file).to.have.property('hash')) expect(files.length).to.equal(1) expect(files[0].path).to.equal('200Bytes.txt') + expect(files[0].hash).to.deep.equal(targetFileCid.buffer) fileEql(files[0], content, cb) } ], done) diff --git a/test/exporter.spec.js b/test/exporter.spec.js index c99dcc3..2ac452a 100644 --- a/test/exporter.spec.js +++ b/test/exporter.spec.js @@ -229,7 +229,7 @@ describe('exporter', () => { }) }) - it('small file in a directory with an escaped slash in the title', (done) => { + it.only('small file in a directory with an escaped slash in the title', (done) => { const fileName = `small-\\/file-${Math.random()}.txt` const filePath = `/foo/${fileName}`