From 561ce35ba575558a1362f0aec9f888a02eec3b7d Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 12 Nov 2020 12:48:15 +0000 Subject: [PATCH] feat: support multiple roots It's never been clear why js-ipfs doesn't support multiple roots when go-ipfs does. This PR removes the check for multiple roots so if you import five files without a leading directory in their paths or with the `wrapWithDirectory` option, you'll get five CIDs back instead of an error. --- .../ipfs-unixfs-importer/src/tree-builder.js | 42 +++++++++---------- .../test/importer.spec.js | 22 ++++------ 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/packages/ipfs-unixfs-importer/src/tree-builder.js b/packages/ipfs-unixfs-importer/src/tree-builder.js index 46012697..1b13fee6 100644 --- a/packages/ipfs-unixfs-importer/src/tree-builder.js +++ b/packages/ipfs-unixfs-importer/src/tree-builder.js @@ -4,8 +4,6 @@ const DirFlat = require('./dir-flat') const flatToShard = require('./flat-to-shard') const Dir = require('./dir') const toPathComponents = require('./utils/to-path-components') -const errCode = require('err-code') -const first = require('it-first') async function addToTree (elem, tree, options) { const pathElems = toPathComponents(elem.path || '') @@ -51,6 +49,18 @@ async function addToTree (elem, tree, options) { return tree } +async function * flushAndYield (tree, block) { + if (!(tree instanceof Dir)) { + if (tree && tree.unixfs && tree.unixfs.isDirectory()) { + yield tree + } + + return + } + + yield * tree.flush(tree.path, block) +} + async function * treeBuilder (source, block, options) { let tree = new DirFlat({ root: true, @@ -72,29 +82,17 @@ async function * treeBuilder (source, block, options) { } } - if (!options.wrapWithDirectory) { - if (tree.childCount() > 1) { - throw errCode(new Error('detected more than one root'), 'ERR_MORE_THAN_ONE_ROOT') - } - - const unwrapped = await first(tree.eachChildSeries()) - - if (!unwrapped) { - return - } - - tree = unwrapped.child - } + if (options.wrapWithDirectory) { + yield * flushAndYield(tree, block) + } else { + for await (const unwrapped of tree.eachChildSeries()) { + if (!unwrapped) { + continue + } - if (!(tree instanceof Dir)) { - if (tree && tree.unixfs && tree.unixfs.isDirectory()) { - yield tree + yield * flushAndYield(unwrapped.child, block) } - - return } - - yield * tree.flush(tree.path, block) } module.exports = treeBuilder diff --git a/packages/ipfs-unixfs-importer/test/importer.spec.js b/packages/ipfs-unixfs-importer/test/importer.spec.js index be8f336b..33696cb1 100644 --- a/packages/ipfs-unixfs-importer/test/importer.spec.js +++ b/packages/ipfs-unixfs-importer/test/importer.spec.js @@ -376,20 +376,16 @@ strategies.forEach((strategy) => { expect(files[0].cid.toBaseEncodedString()).to.eql('QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH') }) - it('fails on more than one root', async () => { - try { - await all(importer([{ - path: 'beep/200Bytes.txt', - content: smallFile - }, { - path: 'boop/200Bytes.txt', - content: bigFile - }], block, options)) + it('supports more than one root', async () => { + const files = await all(importer([{ + path: '200Bytes.txt', + content: smallFile + }, { + path: '200Bytes.txt', + content: bigFile + }], block, options)) - throw new Error('No error was thrown') - } catch (err) { - expect(err.code).to.equal('ERR_MORE_THAN_ONE_ROOT') - } + expect(files).to.have.lengthOf(2) }) it('accepts strings as content', async () => {