From 813048ffb32a11cfefc51c2ec8634faaff2a924e Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 21 May 2019 13:08:17 +0100 Subject: [PATCH] refactor: update ipld formats, async/await mfs/unixfs & base32 cids (#2068) This is part of the Awesome Endeavour: Async Iterators: https://github.com/ipfs/js-ipfs/issues/1670 Depends on * [x] ipld/js-ipld-dag-pb#137 * [x] ipfs/interface-js-ipfs-core#473 * [x] ipfs/js-ipfs-http-client#1010 * [x] ipfs/js-ipfs-http-response#25 resolves #1995 BREAKING CHANGE: The default string encoding for version 1 CIDs has changed to `base32`. IPLD formats have been updated to the latest versions. IPLD nodes returned by `ipfs.dag` and `ipfs.object` commands have significant breaking changes. If you are using these commands in your application you are likely to encounter the following changes to `dag-pb` nodes (the default node type that IPFS creates): * `DAGNode` properties have been renamed as follows: * `data` => `Data` * `links` => `Links` * `size` => `size` (Note: no change) * `DAGLink` properties have been renamed as follows: * `cid` => `Hash` * `name` => `Name` * `size` => `Tsize` See CHANGELOGs for each IPLD format for it's respective changes, you can read more about the [`dag-pb` changes in the CHANGELOG](https://github.com/ipld/js-ipld-dag-pb/blob/master) License: MIT Signed-off-by: Alan Shaw --- .../get-path-accross-formats.js | 19 +- examples/traverse-ipld-graphs/tree.js | 19 +- package.json | 53 ++-- src/cli/bin.js | 14 +- src/cli/commands/dag/get.js | 2 +- src/cli/commands/object/get.js | 14 +- src/cli/commands/object/links.js | 4 +- src/cli/commands/object/patch/add-link.js | 12 +- src/core/components/bitswap.js | 2 +- src/core/components/dag.js | 70 ++++- src/core/components/files-mfs.js | 99 ++++++- .../files-regular/add-pull-stream.js | 42 +-- .../files-regular/cat-pull-stream.js | 28 +- .../files-regular/get-pull-stream.js | 17 +- .../files-regular/ls-pull-stream.js | 61 +++-- .../files-regular/refs-pull-stream.js | 20 +- src/core/components/files-regular/utils.js | 32 ++- src/core/components/init.js | 18 +- src/core/components/object.js | 243 ++++++++++++------ src/core/components/pin-set.js | 55 ++-- src/core/components/pin.js | 57 +++- src/core/components/resolve.js | 73 ++---- src/core/runtime/ipld-nodejs.js | 34 +-- src/core/utils.js | 9 +- src/http/api/resources/dag.js | 53 ++-- src/http/api/resources/files-regular.js | 2 +- src/http/api/resources/object.js | 36 +-- src/http/gateway/resources/gateway.js | 2 +- src/utils/cid.js | 1 - test/cli/block.js | 2 +- test/cli/dag.js | 7 +- test/cli/dht.js | 4 +- test/cli/files.js | 12 +- test/cli/name-pubsub.js | 8 +- test/cli/name.js | 10 +- test/cli/object.js | 24 +- test/cli/pin.js | 4 +- test/cli/ping.js | 6 +- test/cli/pubsub.js | 4 +- test/cli/resolve.js | 6 +- test/cli/swarm.js | 6 +- test/core/bitswap.spec.js | 4 +- test/core/files.spec.js | 4 +- test/core/init.spec.js | 2 +- test/core/kad-dht.node.js | 4 +- test/core/object.spec.js | 8 +- test/core/pin-set.js | 35 +-- test/core/ping.spec.js | 4 +- test/core/preload.spec.js | 6 +- test/http-api/block.js | 4 +- test/http-api/bootstrap.js | 4 +- test/http-api/config.js | 2 +- test/http-api/dns.js | 4 +- test/http-api/files.js | 4 +- test/http-api/id.js | 2 +- test/http-api/inject/dag.js | 20 +- test/http-api/interface.js | 3 +- test/http-api/object.js | 7 +- test/http-api/version.js | 4 +- test/utils/ipfs-exec.js | 7 +- test/utils/on-and-off.js | 3 +- 61 files changed, 812 insertions(+), 503 deletions(-) diff --git a/examples/traverse-ipld-graphs/get-path-accross-formats.js b/examples/traverse-ipld-graphs/get-path-accross-formats.js index 984e9f234d..a5fa1f101c 100644 --- a/examples/traverse-ipld-graphs/get-path-accross-formats.js +++ b/examples/traverse-ipld-graphs/get-path-accross-formats.js @@ -17,19 +17,20 @@ createNode((err, ipfs) => { series([ (cb) => { const someData = Buffer.from('capoeira') + let node - dagPB.DAGNode.create(someData, (err, node) => { + try { + node = dagPB.DAGNode.create(someData) + } catch (err) { + return cb(err) + } + + ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }, (err, cid) => { if (err) { cb(err) } - - ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }, (err, cid) => { - if (err) { - cb(err) - } - cidPBNode = cid - cb() - }) + cidPBNode = cid + cb() }) }, (cb) => { diff --git a/examples/traverse-ipld-graphs/tree.js b/examples/traverse-ipld-graphs/tree.js index 920f7a2bb3..e4c2da6b34 100644 --- a/examples/traverse-ipld-graphs/tree.js +++ b/examples/traverse-ipld-graphs/tree.js @@ -17,19 +17,20 @@ createNode((err, ipfs) => { series([ (cb) => { const someData = Buffer.from('capoeira') + let node - dagPB.DAGNode.create(someData, (err, node) => { + try { + dagPB.DAGNode.create(someData) + } catch (err) { + return cb(err) + } + + ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }, (err, cid) => { if (err) { cb(err) } - - ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }, (err, cid) => { - if (err) { - cb(err) - } - cidPBNode = cid - cb() - }) + cidPBNode = cid + cb() }) }, (cb) => { diff --git a/package.json b/package.json index 2acef0c4cc..389cf3aec0 100644 --- a/package.json +++ b/package.json @@ -72,12 +72,12 @@ "execa": "^1.0.0", "form-data": "^2.3.3", "hat": "0.0.3", + "interface-ipfs-core": "~0.103.0", "ipfsd-ctl": "~0.42.0", "libp2p-websocket-star": "~0.10.2", "ncp": "^2.0.0", "qs": "^6.5.2", "rimraf": "^2.6.2", - "interface-ipfs-core": "~0.102.0", "sinon": "^7.3.1", "stream-to-promise": "^2.2.0" }, @@ -86,6 +86,9 @@ "@hapi/hapi": "^18.3.1", "@hapi/joi": "^15.0.1", "async": "^2.6.1", + "async-iterator-all": "0.0.2", + "async-iterator-to-pull-stream": "^1.1.0", + "async-iterator-to-stream": "^1.1.0", "base32.js": "~0.1.0", "bignumber.js": "^8.0.2", "binary-querystring": "~0.1.2", @@ -94,8 +97,9 @@ "bs58": "^4.0.1", "buffer-peek-stream": "^1.0.1", "byteman": "^1.3.5", - "cid-tool": "~0.2.0", - "cids": "~0.5.8", + "callbackify": "^1.1.0", + "cid-tool": "~0.3.0", + "cids": "~0.7.1", "class-is": "^1.1.0", "datastore-core": "~0.6.0", "datastore-pubsub": "~0.1.1", @@ -109,39 +113,39 @@ "glob": "^7.1.3", "hapi-pino": "^6.0.0", "human-to-milliseconds": "^1.0.0", - "interface-datastore": "~0.7.0", - "ipfs-bitswap": "~0.23.0", - "ipfs-block": "~0.8.0", + "interface-datastore": "~0.6.0", + "ipfs-bitswap": "~0.24.0", + "ipfs-block": "~0.8.1", "ipfs-block-service": "~0.15.1", - "ipfs-http-client": "^31.1.0", - "ipfs-http-response": "~0.2.1", - "ipfs-mfs": "~0.10.2", + "ipfs-http-client": "^32.0.0", + "ipfs-http-response": "~0.3.0", + "ipfs-mfs": "~0.11.2", "ipfs-multipart": "~0.1.0", - "ipfs-repo": "~0.26.5", + "ipfs-repo": "~0.26.6", "ipfs-unixfs": "~0.1.16", - "ipfs-unixfs-exporter": "~0.36.1", - "ipfs-unixfs-importer": "~0.38.5", - "ipld": "~0.21.1", - "ipld-bitcoin": "~0.1.8", - "ipld-dag-cbor": "~0.13.1", - "ipld-dag-pb": "~0.15.3", - "ipld-ethereum": "^2.0.1", - "ipld-git": "~0.3.0", - "ipld-raw": "^2.0.1", - "ipld-zcash": "~0.1.6", + "ipfs-unixfs-exporter": "~0.37.4", + "ipfs-unixfs-importer": "~0.39.6", + "ipfs-utils": "~0.0.3", + "ipld": "~0.24.1", + "ipld-bitcoin": "~0.3.0", + "ipld-dag-cbor": "~0.15.0", + "ipld-dag-pb": "~0.17.3", + "ipld-ethereum": "^4.0.0", + "ipld-git": "~0.5.0", + "ipld-raw": "^4.0.0", + "ipld-zcash": "~0.3.0", "ipns": "~0.5.0", - "is-ipfs": "~0.6.0", + "is-ipfs": "~0.6.1", "is-pull-stream": "~0.0.0", "is-stream": "^2.0.0", "iso-url": "~0.4.6", - "ipfs-utils": "~0.0.3", "just-flatten-it": "^2.1.0", "just-safe-set": "^2.1.0", "kind-of": "^6.0.2", "libp2p": "~0.25.3", "libp2p-bootstrap": "~0.9.3", "libp2p-crypto": "~0.16.0", - "libp2p-kad-dht": "~0.14.12", + "libp2p-kad-dht": "~0.15.0", "libp2p-keychain": "~0.4.1", "libp2p-mdns": "~0.12.0", "libp2p-record": "~0.6.1", @@ -158,7 +162,7 @@ "multiaddr": "^6.0.5", "multiaddr-to-uri": "^4.0.1", "multibase": "~0.6.0", - "multicodec": "~0.5.0", + "multicodec": "~0.5.1", "multihashes": "~0.4.14", "multihashing-async": "~0.6.0", "node-fetch": "^2.3.0", @@ -177,6 +181,7 @@ "pull-pushable": "^2.2.0", "pull-sort": "^1.0.1", "pull-stream": "^3.6.9", + "pull-stream-to-async-iterator": "^1.0.1", "pull-stream-to-stream": "^1.3.4", "pull-traverse": "^1.0.3", "readable-stream": "^3.1.1", diff --git a/src/cli/bin.js b/src/cli/bin.js index 7c283bff9b..8473c7a9c1 100755 --- a/src/cli/bin.js +++ b/src/cli/bin.js @@ -2,6 +2,18 @@ 'use strict' +process.on('uncaughtException', (err) => { + console.info(err) + + throw err +}) + +process.on('unhandledRejection', (err) => { + console.info(err) + + throw err +}) + const YargsPromise = require('yargs-promise') const updateNotifier = require('update-notifier') const utils = require('./utils') @@ -35,7 +47,7 @@ async function main (args) { } }) .catch(({ error, argv }) => { - getIpfs = argv.getIpfs + getIpfs = argv && argv.getIpfs debug(error) // the argument can have a different shape depending on where the error came from if (error.message || (error.error && error.error.message)) { diff --git a/src/cli/commands/dag/get.js b/src/cli/commands/dag/get.js index 0fb720ca5c..bf9fe04663 100644 --- a/src/cli/commands/dag/get.js +++ b/src/cli/commands/dag/get.js @@ -32,7 +32,7 @@ module.exports = { try { result = await ipfs.dag.get(cid, path, options) } catch (err) { - return print(`dag get failed: ${err.message}`) + return print(`dag get failed: ${err}`) } if (options.localResolve) { diff --git a/src/cli/commands/object/get.js b/src/cli/commands/object/get.js index 6bbaa887e0..ac569ab62f 100644 --- a/src/cli/commands/object/get.js +++ b/src/cli/commands/object/get.js @@ -25,21 +25,21 @@ module.exports = { resolve((async () => { const ipfs = await getIpfs() const node = await ipfs.object.get(key, { enc: 'base58' }) - let data = node.data + let data = node.Data || '' if (Buffer.isBuffer(data)) { - data = node.data.toString(dataEncoding || undefined) + data = node.Data.toString(dataEncoding || undefined) } const answer = { Data: data, Hash: cidToString(key, { base: cidBase, upgrade: false }), - Size: node.size, - Links: node.links.map((l) => { + Size: node.Size, + Links: node.Links.map((l) => { return { - Name: l.name, - Size: l.size, - Hash: cidToString(l.cid, { base: cidBase, upgrade: false }) + Name: l.Name, + Size: l.Tsize, + Hash: cidToString(l.Hash, { base: cidBase, upgrade: false }) } }) } diff --git a/src/cli/commands/object/links.js b/src/cli/commands/object/links.js index feb93596c7..21bb9ca6b8 100644 --- a/src/cli/commands/object/links.js +++ b/src/cli/commands/object/links.js @@ -23,8 +23,8 @@ module.exports = { const links = await ipfs.object.links(key, { enc: 'base58' }) links.forEach((link) => { - const cidStr = cidToString(link.cid, { base: cidBase, upgrade: false }) - print(`${cidStr} ${link.size} ${link.name}`) + const cidStr = cidToString(link.Hash, { base: cidBase, upgrade: false }) + print(`${cidStr} ${link.Tsize} ${link.Name}`) }) })()) } diff --git a/src/cli/commands/object/patch/add-link.js b/src/cli/commands/object/patch/add-link.js index 069060052e..e9ae2d082c 100644 --- a/src/cli/commands/object/patch/add-link.js +++ b/src/cli/commands/object/patch/add-link.js @@ -3,7 +3,6 @@ const dagPB = require('ipld-dag-pb') const DAGLink = dagPB.DAGLink const multibase = require('multibase') -const promisify = require('promisify-es6') const { print } = require('../../../utils') const { cidToString } = require('../../../../utils/cid') @@ -17,14 +16,21 @@ module.exports = { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', choices: multibase.names + }, + 'cid-version': { + describe: 'The CID version of the DAGNode to link to', + type: 'number', + default: 0 } }, - handler ({ getIpfs, root, name, ref, cidBase, resolve }) { + handler ({ getIpfs, root, name, ref, cidBase, cidVersion, resolve }) { resolve((async () => { const ipfs = await getIpfs() const nodeA = await ipfs.object.get(ref, { enc: 'base58' }) - const result = await promisify(dagPB.util.cid)(nodeA) + const result = await dagPB.util.cid(dagPB.util.serialize(nodeA), { + cidVersion + }) const link = new DAGLink(name, nodeA.size, result) const cid = await ipfs.object.patch.addLink(root, link, { enc: 'base58' }) print(cidToString(cid, { base: cidBase, upgrade: false })) diff --git a/src/core/components/bitswap.js b/src/core/components/bitswap.js index 13787534aa..c25bebacc3 100644 --- a/src/core/components/bitswap.js +++ b/src/core/components/bitswap.js @@ -9,7 +9,7 @@ const PeerId = require('peer-id') const errCode = require('err-code') function formatWantlist (list, cidBase) { - return Array.from(list).map((e) => ({ '/': e[1].cid.toBaseEncodedString() })) + return Array.from(list).map((e) => ({ '/': e[1].cid.toBaseEncodedString(cidBase) })) } module.exports = function bitswap (self) { diff --git a/src/core/components/dag.js b/src/core/components/dag.js index ffc6ccfd0a..5e750c35b0 100644 --- a/src/core/components/dag.js +++ b/src/core/components/dag.js @@ -3,10 +3,12 @@ const promisify = require('promisify-es6') const CID = require('cids') const pull = require('pull-stream') +const iterToPull = require('async-iterator-to-pull-stream') const mapAsync = require('async/map') const setImmediate = require('async/setImmediate') const flattenDeep = require('just-flatten-it') const errCode = require('err-code') +const multicodec = require('multicodec') module.exports = function dag (self) { return { @@ -25,21 +27,44 @@ module.exports = function dag (self) { } const optionDefaults = { - format: 'dag-cbor', - hashAlg: 'sha2-256' + format: multicodec.DAG_CBOR, + hashAlg: multicodec.SHA2_256 } - options = options.cid ? options : Object.assign({}, optionDefaults, options) + // The IPLD expects the format and hashAlg as constants + if (options.format && typeof options.format === 'string') { + const constantName = options.format.toUpperCase().replace(/-/g, '_') + options.format = multicodec[constantName] + } + if (options.hashAlg && typeof options.hashAlg === 'string') { + const constantName = options.hashAlg.toUpperCase().replace(/-/g, '_') + options.hashAlg = multicodec[constantName] + } - self._ipld.put(dagNode, options, (err, cid) => { - if (err) return callback(err) + options = options.cid ? options : Object.assign({}, optionDefaults, options) - if (options.preload !== false) { - self._preload(cid) + // js-ipld defaults to verion 1 CIDs. Hence set version 0 explicitly for + // dag-pb nodes + if (options.version === undefined) { + if (options.format === multicodec.DAG_PB && options.hashAlg === multicodec.SHA2_256) { + options.version = 0 + } else { + options.version = 1 } + } - callback(null, cid) - }) + self._ipld.put(dagNode, options.format, { + hashAlg: options.hashAlg, + cidVersion: options.version + }).then( + (cid) => { + if (options.preload !== false) { + self._preload(cid) + } + return callback(null, cid) + }, + (error) => callback(error) + ) }), get: promisify((cid, path, options, callback) => { @@ -54,7 +79,7 @@ module.exports = function dag (self) { // Allow options in path position if (typeof path !== 'string') { options = path - path = null + path = undefined } else { options = {} } @@ -90,7 +115,24 @@ module.exports = function dag (self) { self._preload(cid) } - self._ipld.get(cid, path, options, callback) + if (path === undefined || path === '/') { + self._ipld.get(cid).then( + (value) => { + callback(null, { + value, + remainderPath: '' + }) + }, + (error) => callback(error) + ) + } else { + const result = self._ipld.resolve(cid, path) + const promisedValue = options.localResolve ? result.first() : result.last() + promisedValue.then( + (value) => callback(null, value), + (error) => callback(error) + ) + } }), tree: promisify((cid, path, options, callback) => { @@ -135,7 +177,7 @@ module.exports = function dag (self) { } pull( - self._ipld.treeStream(cid, path, options), + iterToPull(self._ipld.tree(cid, path, options)), pull.collect(callback) ) }), @@ -162,8 +204,8 @@ module.exports = function dag (self) { self.dag.get(cid, '', options, (err, res) => { if (err) { return callback(err) } - mapAsync(res.value.links, (link, cb) => { - self.dag._getRecursive(link.cid, options, cb) + mapAsync(res.value.Links, (link, cb) => { + self.dag._getRecursive(link.Hash, options, cb) }, (err, nodes) => { // console.log('nodes:', nodes) if (err) return callback(err) diff --git a/src/core/components/files-mfs.js b/src/core/components/files-mfs.js index 531219c4fd..3807e8bf16 100644 --- a/src/core/components/files-mfs.js +++ b/src/core/components/files-mfs.js @@ -1,9 +1,98 @@ 'use strict' const mfs = require('ipfs-mfs/core') +const isPullStream = require('is-pull-stream') +const toPullStream = require('async-iterator-to-pull-stream') +const toReadableStream = require('async-iterator-to-stream') +const pullStreamToAsyncIterator = require('pull-stream-to-async-iterator') +const all = require('async-iterator-all') +const callbackify = require('callbackify') +const PassThrough = require('stream').PassThrough +const pull = require('pull-stream/pull') +const map = require('pull-stream/throughs/map') -module.exports = self => mfs({ - ipld: self._ipld, - repo: self._repo, - repoOwner: self._options.repoOwner -}) +const mapLsFile = (options = {}) => { + const long = options.long || options.l + + return (file) => { + return { + hash: long ? file.cid.toBaseEncodedString(options.cidBase) : '', + name: file.name, + type: long ? file.type : 0, + size: long ? file.size || 0 : 0 + } + } +} + +module.exports = self => { + const methods = mfs({ + ipld: self._ipld, + blocks: self._blockService, + datastore: self._repo.root, + repoOwner: self._options.repoOwner + }) + + return { + cp: callbackify.variadic(methods.cp), + flush: callbackify.variadic(methods.flush), + ls: callbackify.variadic(async (path, options = {}) => { + const files = await all(methods.ls(path, options)) + + return files.map(mapLsFile(options)) + }), + lsReadableStream: (path, options = {}) => { + const stream = toReadableStream.obj(methods.ls(path, options)) + const through = new PassThrough({ + objectMode: true + }) + stream.on('data', (file) => { + through.write(mapLsFile(options)(file)) + }) + stream.on('error', (err) => { + through.destroy(err) + }) + stream.on('end', (file, enc, cb) => { + if (file) { + file = mapLsFile(options)(file) + } + + through.end(file, enc, cb) + }) + + return through + }, + lsPullStream: (path, options = {}) => { + return pull( + toPullStream.source(methods.ls(path, options)), + map(mapLsFile(options)) + ) + }, + mkdir: callbackify.variadic(methods.mkdir), + mv: callbackify.variadic(methods.mv), + read: callbackify(async (path, options = {}) => { + return Buffer.concat(await all(methods.read(path, options))) + }), + readPullStream: (path, options = {}) => { + return toPullStream.source(methods.read(path, options)) + }, + readReadableStream: (path, options = {}) => { + return toReadableStream(methods.read(path, options)) + }, + rm: callbackify.variadic(methods.rm), + stat: callbackify(async (path, options = {}) => { + const stats = await methods.stat(path, options) + + stats.hash = stats.cid.toBaseEncodedString(options && options.cidBase) + delete stats.cid + + return stats + }), + write: callbackify.variadic(async (path, content, options = {}) => { + if (isPullStream.isSource(content)) { + content = pullStreamToAsyncIterator(content) + } + + await methods.write(path, content, options) + }) + } +} diff --git a/src/core/components/files-regular/add-pull-stream.js b/src/core/components/files-regular/add-pull-stream.js index 9937b08852..c976fcf5df 100644 --- a/src/core/components/files-regular/add-pull-stream.js +++ b/src/core/components/files-regular/add-pull-stream.js @@ -2,12 +2,13 @@ const importer = require('ipfs-unixfs-importer') const kindOf = require('kind-of') -const CID = require('cids') +const toAsyncIterator = require('pull-stream-to-async-iterator') +const toPullStream = require('async-iterator-to-pull-stream') +const pull = require('pull-stream/pull') const pullValues = require('pull-stream/sources/values') const pullMap = require('pull-stream/throughs/map') const pullAsyncMap = require('pull-stream/throughs/async-map') const pullFlatten = require('pull-stream/throughs/flatten') -const pull = require('pull-stream/pull') const toPull = require('stream-to-pull-stream') const waterfall = require('async/waterfall') const isStream = require('is-stream') @@ -16,26 +17,23 @@ const { parseChunkerString } = require('./utils') const streamFromFileReader = require('ipfs-utils/src/streams/stream-from-filereader') const { supportsFileReader } = require('ipfs-utils/src/supports') -const WRAPPER = 'wrapper/' - function noop () {} function prepareFile (file, self, opts, callback) { opts = opts || {} - let cid = new CID(file.multihash) - - if (opts.cidVersion === 1) { - cid = cid.toV1() - } + let cid = file.cid waterfall([ (cb) => opts.onlyHash ? cb(null, file) - : self.object.get(file.multihash, Object.assign({}, opts, { preload: false }), cb), + : self.object.get(file.cid, Object.assign({}, opts, { preload: false }), cb), (node, cb) => { - const b58Hash = cid.toBaseEncodedString() + if (opts.cidVersion === 1) { + cid = cid.toV1() + } + const b58Hash = cid.toBaseEncodedString() let size = node.size if (Buffer.isBuffer(node)) { @@ -43,10 +41,9 @@ function prepareFile (file, self, opts, callback) { } cb(null, { - path: opts.wrapWithDirectory - ? file.path.substring(WRAPPER.length) - : (file.path || b58Hash), + path: file.path === undefined ? b58Hash : (file.path || ''), hash: b58Hash, + // multihash: b58Hash, size }) } @@ -90,16 +87,12 @@ function normalizeContent (content, opts) { throw new Error('Must provide a path when wrapping with a directory') } - if (opts.wrapWithDirectory) { - data.path = WRAPPER + data.path - } - return data }) } function preloadFile (file, self, opts) { - const isRootFile = opts.wrapWithDirectory + const isRootFile = !file.path || opts.wrapWithDirectory ? file.path === '' : !file.path.includes('/') @@ -140,7 +133,10 @@ module.exports = function (self) { shardSplitThreshold: self._options.EXPERIMENTAL.sharding ? 1000 : Infinity - }, options, chunkerOptions) + }, options, { + chunker: chunkerOptions.chunker, + chunkerOptions: chunkerOptions.chunkerOptions + }) // CID v0 is for multihashes encoded with sha2-256 if (opts.hashAlg && opts.cidVersion !== 1) { @@ -159,7 +155,11 @@ module.exports = function (self) { return pull( pullMap(content => normalizeContent(content, opts)), pullFlatten(), - importer(self._ipld, opts), + pullMap(file => ({ + path: file.path ? file.path : undefined, + content: file.content ? toAsyncIterator(file.content) : undefined + })), + toPullStream.transform(source => importer(source, self._ipld, opts)), pullAsyncMap((file, cb) => prepareFile(file, self, opts, cb)), pullMap(file => preloadFile(file, self, opts)), pullAsyncMap((file, cb) => pinFile(file, self, opts, cb)) diff --git a/src/core/components/files-regular/cat-pull-stream.js b/src/core/components/files-regular/cat-pull-stream.js index 2c33598f35..a491700d7d 100644 --- a/src/core/components/files-regular/cat-pull-stream.js +++ b/src/core/components/files-regular/cat-pull-stream.js @@ -1,8 +1,8 @@ 'use strict' const exporter = require('ipfs-unixfs-exporter') -const pull = require('pull-stream') const deferred = require('pull-defer') +const toPullStream = require('async-iterator-to-pull-stream') const { normalizePath } = require('./utils') module.exports = function (self) { @@ -15,7 +15,6 @@ module.exports = function (self) { ipfsPath = normalizePath(ipfsPath) const pathComponents = ipfsPath.split('/') - const fileNameOrHash = pathComponents[pathComponents.length - 1] if (options.preload !== false) { self._preload(pathComponents[0]) @@ -23,22 +22,10 @@ module.exports = function (self) { const d = deferred.source() - pull( - exporter(ipfsPath, self._ipld, options), - pull.filter(file => file.path === fileNameOrHash), - pull.take(1), - pull.collect((err, files) => { - if (err) { - return d.abort(err) - } - - if (!files.length) { - return d.abort(new Error('No such file')) - } - - const file = files[0] - - if (!file.content && file.type === 'dir') { + exporter(ipfsPath, self._ipld, options) + .then(file => { + // File may not have unixfs prop if small & imported with rawLeaves true + if (file.unixfs && file.unixfs.type.includes('dir')) { return d.abort(new Error('this dag node is a directory')) } @@ -46,9 +33,10 @@ module.exports = function (self) { return d.abort(new Error('this dag node has no content')) } - d.resolve(file.content) + d.resolve(toPullStream.source(file.content(options))) + }, err => { + d.abort(err) }) - ) return d } diff --git a/src/core/components/files-regular/get-pull-stream.js b/src/core/components/files-regular/get-pull-stream.js index c47ec44f59..e564f67d3e 100644 --- a/src/core/components/files-regular/get-pull-stream.js +++ b/src/core/components/files-regular/get-pull-stream.js @@ -1,9 +1,11 @@ 'use strict' const exporter = require('ipfs-unixfs-exporter') -const pull = require('pull-stream') +const toPullStream = require('async-iterator-to-pull-stream') const errCode = require('err-code') -const { normalizePath } = require('./utils') +const pull = require('pull-stream/pull') +const map = require('pull-stream/throughs/map') +const { normalizePath, mapFile } = require('./utils') module.exports = function (self) { return (ipfsPath, options) => { @@ -22,12 +24,11 @@ module.exports = function (self) { } return pull( - exporter(ipfsPath, self._ipld, options), - pull.map(file => { - file.hash = file.cid.toString() - delete file.cid - return file - }) + toPullStream.source(exporter.recursive(ipfsPath, self._ipld, options)), + map(mapFile({ + ...options, + includeContent: true + })) ) } } diff --git a/src/core/components/files-regular/ls-pull-stream.js b/src/core/components/files-regular/ls-pull-stream.js index 524bcc5372..e1ec58ce10 100644 --- a/src/core/components/files-regular/ls-pull-stream.js +++ b/src/core/components/files-regular/ls-pull-stream.js @@ -1,8 +1,14 @@ 'use strict' const exporter = require('ipfs-unixfs-exporter') -const pull = require('pull-stream') -const { normalizePath } = require('./utils') +const deferred = require('pull-defer') +const pull = require('pull-stream/pull') +const once = require('pull-stream/sources/once') +const map = require('pull-stream/throughs/map') +const filter = require('pull-stream/throughs/filter') +const errCode = require('err-code') +const toPullStream = require('async-iterator-to-pull-stream') +const { normalizePath, mapFile } = require('./utils') module.exports = function (self) { return function (ipfsPath, options) { @@ -11,25 +17,48 @@ module.exports = function (self) { const path = normalizePath(ipfsPath) const recursive = options.recursive const pathComponents = path.split('/') - const pathDepth = pathComponents.length - const maxDepth = recursive ? global.Infinity : pathDepth - options.maxDepth = options.maxDepth || maxDepth if (options.preload !== false) { self._preload(pathComponents[0]) } - return pull( - exporter(ipfsPath, self._ipld, options), - pull.filter(node => - recursive ? node.depth >= pathDepth : node.depth === pathDepth - ), - pull.map(node => { - node.hash = node.cid.toString() - delete node.cid - delete node.content - return node + const d = deferred.source() + + exporter(ipfsPath, self._ipld, options) + .then(file => { + if (!file.unixfs) { + return d.abort(errCode(new Error('dag node was not a UnixFS node'), 'ENOTUNIXFS')) + } + + if (file.unixfs.type === 'file') { + return d.resolve(once(mapFile(options)(file))) + } + + if (file.unixfs.type.includes('dir')) { + if (recursive) { + return d.resolve(pull( + toPullStream.source(exporter.recursive(file.cid, self._ipld, options)), + filter(child => file.cid.toBaseEncodedString() !== child.cid.toBaseEncodedString()), + map(mapFile(options)) + )) + } + + return d.resolve(pull( + toPullStream.source(file.content()), + map(mapFile(options)), + map((file) => { + file.depth-- + + return file + }) + )) + } + + d.abort(errCode(new Error(`Unknown UnixFS type ${file.unixfs.type}`), 'EUNKNOWNUNIXFSTYPE')) + }, err => { + d.abort(err) }) - ) + + return d } } diff --git a/src/core/components/files-regular/refs-pull-stream.js b/src/core/components/files-regular/refs-pull-stream.js index a229054e62..aec4ba8a6d 100644 --- a/src/core/components/files-regular/refs-pull-stream.js +++ b/src/core/components/files-regular/refs-pull-stream.js @@ -6,6 +6,7 @@ const pullTraverse = require('pull-traverse') const pullCat = require('pull-cat') const isIpfs = require('is-ipfs') const CID = require('cids') +const { DAGNode } = require('ipld-dag-pb') const { normalizePath } = require('./utils') const { Format } = require('./refs') @@ -147,12 +148,19 @@ function objectStream (ipfs, rootCid, maxDepth, isUnique) { // Fetch a node from IPLD then get all its links function getLinks (ipfs, cid, callback) { - ipfs._ipld.get(new CID(cid), (err, node) => { - if (err) { - return callback(err) - } - callback(null, node.value.links || getNodeLinks(node.value)) - }) + ipfs._ipld.get(new CID(cid)) + .then(node => { + let links + if (DAGNode.isDAGNode(node)) { + links = node.Links.map(({ Name, Hash }) => { + return { name: Name, cid: new CID(Hash) } + }) + } else { + links = getNodeLinks(node) + } + callback(null, links) + }) + .catch(callback) } // Recursively search the node for CIDs diff --git a/src/core/components/files-regular/utils.js b/src/core/components/files-regular/utils.js index abda5f6d85..9502447393 100644 --- a/src/core/components/files-regular/utils.js +++ b/src/core/components/files-regular/utils.js @@ -2,6 +2,8 @@ const CID = require('cids') const { Buffer } = require('buffer') +const { cidToString } = require('../../../utils/cid') +const toPullStream = require('async-iterator-to-pull-stream') const normalizePath = (path) => { if (Buffer.isBuffer(path)) { @@ -99,9 +101,37 @@ const parseChunkSize = (str, name) => { return size } +const mapFile = (options = {}) => { + return (file) => { + let size = 0 + let type = 'dir' + + if (file.unixfs && file.unixfs.type === 'file') { + size = file.unixfs.fileSize() + type = 'file' + } + + const output = { + hash: cidToString(file.cid, { base: options.cidBase }), + path: file.path, + name: file.name, + depth: file.path.split('/').length, + size, + type + } + + if (options.includeContent && file.unixfs && file.unixfs.type === 'file') { + output.content = toPullStream.source(file.content()) + } + + return output + } +} + module.exports = { normalizePath, parseChunkSize, parseRabinString, - parseChunkerString + parseChunkerString, + mapFile } diff --git a/src/core/components/init.js b/src/core/components/init.js index 96b8572baf..5b1a1b7cbe 100644 --- a/src/core/components/init.js +++ b/src/core/components/init.js @@ -11,6 +11,7 @@ const { DAGNode } = require('ipld-dag-pb') const UnixFs = require('ipfs-unixfs') +const multicodec = require('multicodec') const IPNS = require('../ipns') const OfflineDatastore = require('../ipns/routing/offline-datastore') @@ -129,12 +130,21 @@ module.exports = function init (self) { const tasks = [ (cb) => { waterfall([ - (cb) => DAGNode.create(new UnixFs('directory').marshal(), cb), + (cb) => { + try { + cb(null, DAGNode.create(new UnixFs('directory').marshal())) + } catch (err) { + cb(err) + } + }, (node, cb) => self.dag.put(node, { version: 0, - format: 'dag-pb', - hashAlg: 'sha2-256' - }, cb), + format: multicodec.DAG_PB, + hashAlg: multicodec.SHA2_256 + }).then( + (cid) => cb(null, cid), + (error) => cb(error) + ), (cid, cb) => self._ipns.initializeKeyspace(privateKey, cid.toBaseEncodedString(), cb) ], cb) } diff --git a/src/core/components/object.js b/src/core/components/object.js index 85a3137522..9db82771eb 100644 --- a/src/core/components/object.js +++ b/src/core/components/object.js @@ -9,6 +9,7 @@ const DAGNode = dagPB.DAGNode const DAGLink = dagPB.DAGLink const CID = require('cids') const mh = require('multihashes') +const multicodec = require('multicodec') const Unixfs = require('ipfs-unixfs') const errCode = require('err-code') @@ -58,11 +59,52 @@ function parseJSONBuffer (buf, callback) { return callback(new Error('failed to parse JSON: ' + err)) } - DAGNode.create(data, links, callback) + try { + callback(null, DAGNode.create(data, links)) + } catch (err) { + callback(err) + } } function parseProtoBuffer (buf, callback) { - dagPB.util.deserialize(buf, callback) + let obj + try { + obj = dagPB.util.deserialize(buf) + } catch (err) { + return callback(err) + } + callback(null, obj) +} + +function findLinks (node, links = []) { + for (let key in node) { + const val = node[key] + + if (key === '/' && Object.keys(node).length === 1) { + try { + links.push(new DAGLink('', 0, new CID(val))) + continue + } catch (_) { + // not a CID + } + } + + if (CID.isCID(val)) { + links.push(new DAGLink('', 0, val)) + + continue + } + + if (Array.isArray(val)) { + findLinks(val, links) + } + + if (typeof val === 'object' && !(val instanceof String)) { + findLinks(val, links) + } + } + + return links } module.exports = function object (self) { @@ -87,19 +129,19 @@ module.exports = function object (self) { return cb(err) } - self._ipld.put(node, { - version: 0, - hashAlg: 'sha2-256', - format: 'dag-pb' - }, (err, cid) => { - if (err) return cb(err) - - if (options.preload !== false) { - self._preload(cid) - } - - cb(null, cid) - }) + self._ipld.put(node, multicodec.DAG_PB, { + cidVersion: 0, + hashAlg: multicodec.SHA2_256 + }).then( + (cid) => { + if (options.preload !== false) { + self._preload(cid) + } + + cb(null, cid) + }, + (error) => cb(error) + ) }) } ], callback) @@ -132,27 +174,27 @@ module.exports = function object (self) { data = Buffer.alloc(0) } - DAGNode.create(data, (err, node) => { - if (err) { - return callback(err) - } + let node - self._ipld.put(node, { - version: 0, - hashAlg: 'sha2-256', - format: 'dag-pb' - }, (err, cid) => { - if (err) { - return callback(err) - } + try { + node = DAGNode.create(data) + } catch (err) { + return callback(err) + } + self._ipld.put(node, multicodec.DAG_PB, { + cidVersion: 0, + hashAlg: multicodec.SHA2_256 + }).then( + (cid) => { if (options.preload !== false) { self._preload(cid) } callback(null, cid) - }) - }) + }, + (error) => callback(error) + ) }), put: promisify((obj, options, callback) => { if (typeof options === 'function') { @@ -175,46 +217,44 @@ module.exports = function object (self) { next() }) } else { - DAGNode.create(obj, (err, _node) => { - if (err) { - return callback(err) - } - node = _node - next() - }) + try { + node = DAGNode.create(obj) + } catch (err) { + return callback(err) + } + + next() } } else if (DAGNode.isDAGNode(obj)) { // already a dag node node = obj next() } else if (typeof obj === 'object') { - DAGNode.create(obj.Data, obj.Links, (err, _node) => { - if (err) { - return callback(err) - } - node = _node - next() - }) + try { + node = DAGNode.create(obj.Data, obj.Links) + } catch (err) { + return callback(err) + } + + next() } else { return callback(new Error('obj not recognized')) } function next () { - self._ipld.put(node, { - version: 0, - hashAlg: 'sha2-256', - format: 'dag-pb' - }, (err, cid) => { - if (err) { - return callback(err) - } - - if (options.preload !== false) { - self._preload(cid) - } + self._ipld.put(node, multicodec.DAG_PB, { + cidVersion: 0, + hashAlg: multicodec.SHA2_256 + }).then( + (cid) => { + if (options.preload !== false) { + self._preload(cid) + } - callback(null, cid) - }) + callback(null, cid) + }, + (error) => callback(error) + ) } }), @@ -248,13 +288,10 @@ module.exports = function object (self) { self._preload(cid) } - self._ipld.get(cid, (err, result) => { - if (err) { - return callback(err) - } - - callback(null, result.value) - }) + self._ipld.get(cid).then( + (node) => callback(null, node), + (error) => callback(error) + ) }), data: promisify((multihash, options, callback) => { @@ -268,7 +305,7 @@ module.exports = function object (self) { return callback(err) } - callback(null, node.data) + callback(null, node.Data) }) }), @@ -278,12 +315,28 @@ module.exports = function object (self) { options = {} } - self.object.get(multihash, options, (err, node) => { + const cid = new CID(multihash) + + self.dag.get(cid, options, (err, result) => { if (err) { return callback(err) } - callback(null, node.links) + if (cid.codec === 'raw') { + return callback(null, []) + } + + if (cid.codec === 'dag-pb') { + return callback(null, result.value.Links) + } + + if (cid.codec === 'dag-cbor') { + const links = findLinks(result) + + callback(null, links) + } + + callback(new Error(`Cannot resolve links from codec ${cid.codec}`)) }) }), @@ -298,9 +351,17 @@ module.exports = function object (self) { waterfall([ (cb) => self.object.get(multihash, options, cb), (node, cb) => { + cb(null, { + node, + serialized: dagPB.util.serialize(node) + }) + }, + ({ node, serialized }, cb) => { parallel({ - serialized: (next) => dagPB.util.serialize(node, next), - cid: (next) => dagPB.util.cid(node, next), + serialized: (next) => next(null, serialized), + cid: (next) => dagPB.util.cid(serialized, { + cidVersion: 0 + }).then((cid) => next(null, cid), next), node: (next) => next(null, node) }, cb) } @@ -310,14 +371,14 @@ module.exports = function object (self) { } const blockSize = result.serialized.length - const linkLength = result.node.links.reduce((a, l) => a + l.size, 0) + const linkLength = result.node.Links.reduce((a, l) => a + l.Tsize, 0) callback(null, { Hash: result.cid.toBaseEncodedString(), - NumLinks: result.node.links.length, + NumLinks: result.node.Links.length, BlockSize: blockSize, - LinksSize: blockSize - result.node.data.length, - DataSize: result.node.data.length, + LinksSize: blockSize - result.node.Data.length, + DataSize: result.node.Data.length, CumulativeSize: blockSize + linkLength }) }) @@ -326,31 +387,49 @@ module.exports = function object (self) { patch: promisify({ addLink (multihash, link, options, callback) { editAndSave((node, cb) => { - DAGNode.addLink(node, link, cb) + DAGNode.addLink(node, link).then((node) => { + cb(null, node) + }, cb) })(multihash, options, callback) }, rmLink (multihash, linkRef, options, callback) { editAndSave((node, cb) => { - if (DAGLink.isDAGLink(linkRef)) { - linkRef = linkRef._name - } else if (linkRef && linkRef.name) { - linkRef = linkRef.name + linkRef = linkRef.Name || linkRef.name + + try { + node = DAGNode.rmLink(node, linkRef) + } catch (err) { + return cb(err) } - DAGNode.rmLink(node, linkRef, cb) + + cb(null, node) })(multihash, options, callback) }, appendData (multihash, data, options, callback) { editAndSave((node, cb) => { - const newData = Buffer.concat([node.data, data]) - DAGNode.create(newData, node.links, cb) + const newData = Buffer.concat([node.Data, data]) + + try { + node = DAGNode.create(newData, node.Links) + } catch (err) { + return cb(err) + } + + cb(null, node) })(multihash, options, callback) }, setData (multihash, data, options, callback) { editAndSave((node, cb) => { - DAGNode.create(data, node.links, cb) + try { + node = DAGNode.create(data, node.Links) + } catch (err) { + return cb(err) + } + + cb(null, node) })(multihash, options, callback) } }) diff --git a/src/core/components/pin-set.js b/src/core/components/pin-set.js index 31ecfffdf0..6f3a9f98dc 100644 --- a/src/core/components/pin-set.js +++ b/src/core/components/pin-set.js @@ -6,6 +6,7 @@ const protobuf = require('protons') const fnv1a = require('fnv1a') const varint = require('varint') const { DAGNode, DAGLink } = require('ipld-dag-pb') +const multicodec = require('multicodec') const someSeries = require('async/someSeries') const eachOfSeries = require('async/eachOfSeries') @@ -24,7 +25,7 @@ function toB58String (hash) { function readHeader (rootNode) { // rootNode.data should be a buffer of the format: // < varint(headerLength) | header | itemData... > - const rootData = rootNode.data + const rootData = rootNode.Data const hdrLength = varint.decode(rootData) const vBytes = varint.decode.bytes if (vBytes <= 0) { @@ -38,7 +39,7 @@ function readHeader (rootNode) { if (header.version !== 1) { throw new Error(`Unsupported Set version: ${header.version}`) } - if (header.fanout > rootNode.links.length) { + if (header.fanout > rootNode.Links.length) { throw new Error('Impossibly large fanout') } return { @@ -69,7 +70,8 @@ exports = module.exports = function (dag) { return searchChildren(root, callback) function searchChildren (root, cb) { - someSeries(root.links, ({ cid }, done) => { + someSeries(root.Links, (link, done) => { + const cid = link.Hash const bs58Link = toB58String(cid) if (bs58Link === childhash) { @@ -110,8 +112,8 @@ exports = module.exports = function (dag) { dag.put(rootNode, { version: 0, - format: 'dag-pb', - hashAlg: 'sha2-256', + format: multicodec.DAG_PB, + hashAlg: multicodec.SHA2_256, preload: false }, (err, cid) => { if (err) { return callback(err, cid) } @@ -146,17 +148,22 @@ exports = module.exports = function (dag) { }) }) // sorting makes any ordering of `pins` produce the same DAGNode - .sort((a, b) => Buffer.compare(a.link.cid.buffer, b.link.cid.buffer)) + .sort((a, b) => Buffer.compare(a.link.Hash.buffer, b.link.Hash.buffer)) const rootLinks = fanoutLinks.concat(nodes.map(item => item.link)) const rootData = Buffer.concat( [headerBuf].concat(nodes.map(item => item.data)) ) - DAGNode.create(rootData, rootLinks, (err, rootNode) => { - if (err) { return storePinsCb(err) } - return storePinsCb(null, rootNode) - }) + let rootNode + + try { + rootNode = DAGNode.create(rootData, rootLinks) + } catch (err) { + return storePinsCb(err) + } + + return storePinsCb(null, rootNode) } else { // If the array of pins is > maxItems, we: // - distribute the pins among `defaultFanout` bins @@ -182,10 +189,16 @@ exports = module.exports = function (dag) { ) }, err => { if (err) { return storePinsCb(err) } - DAGNode.create(headerBuf, fanoutLinks, (err, rootNode) => { - if (err) { return storePinsCb(err) } - return storePinsCb(null, rootNode) - }) + + let rootNode + + try { + rootNode = DAGNode.create(headerBuf, fanoutLinks) + } catch (err) { + return storePinsCb(err) + } + + return storePinsCb(null, rootNode) }) } @@ -194,8 +207,8 @@ exports = module.exports = function (dag) { const opts = { version: 0, - hashAlg: 'sha2-256', - format: 'dag-pb', + format: multicodec.DAG_PB, + hashAlg: multicodec.SHA2_256, preload: false } @@ -209,15 +222,15 @@ exports = module.exports = function (dag) { }, loadSet: (rootNode, name, callback) => { - const link = rootNode.links.find(l => l.name === name) + const link = rootNode.Links.find(l => l.Name === name) if (!link) { return callback(new Error('No link found with name ' + name)) } - dag.get(link.cid, '', { preload: false }, (err, res) => { + dag.get(link.Hash, '', { preload: false }, (err, res) => { if (err) { return callback(err) } const keys = [] - const step = link => keys.push(link.cid.buffer) + const step = link => keys.push(link.Hash.buffer) pinSet.walkItems(res.value, step, err => { if (err) { return callback(err) } return callback(null, keys) @@ -233,11 +246,11 @@ exports = module.exports = function (dag) { return callback(err) } - eachOfSeries(node.links, (link, idx, eachCb) => { + eachOfSeries(node.Links, (link, idx, eachCb) => { if (idx < pbh.header.fanout) { // the first pbh.header.fanout links are fanout bins // if a fanout bin is not 'empty', dig into and walk its DAGLinks - const linkHash = link.cid.buffer + const linkHash = link.Hash.buffer if (!emptyKey.equals(linkHash)) { // walk the links of this fanout bin diff --git a/src/core/components/pin.js b/src/core/components/pin.js index e74427a96a..0afa939e38 100644 --- a/src/core/components/pin.js +++ b/src/core/components/pin.js @@ -15,6 +15,7 @@ const setImmediate = require('async/setImmediate') const { Key } = require('interface-datastore') const errCode = require('err-code') const multibase = require('multibase') +const multicodec = require('multicodec') const createPinSet = require('./pin-set') const { resolvePath } = require('../utils') @@ -59,13 +60,15 @@ module.exports = (self) => { return cb(err) } - map(nodes, (node, cb) => util.cid(node, cb), (err, cids) => { + map(nodes, (node, cb) => util.cid(util.serialize(node), { + cidVersion: 0 + }).then(cid => cb(null, cid), cb), (err, cids) => { if (err) { return cb(err) } cids - .map(cids => cids.toBaseEncodedString()) + .map(cid => cid.toString()) // recursive pins pre-empt indirect pins .filter(key => !recursivePins.has(key)) .forEach(key => indirectKeys.add(key)) @@ -88,36 +91,62 @@ module.exports = (self) => { // create a DAGLink to the node with direct pins cb => waterfall([ cb => pinset.storeSet(directKeys(), cb), - ({ node, cid }, cb) => DAGLink.create(types.direct, node.size, cid, cb), + ({ node, cid }, cb) => { + try { + cb(null, new DAGLink(types.direct, node.size, cid)) + } catch (err) { + cb(err) + } + }, (link, cb) => { dLink = link; cb(null) } ], cb), // create a DAGLink to the node with recursive pins cb => waterfall([ cb => pinset.storeSet(recursiveKeys(), cb), - ({ node, cid }, cb) => DAGLink.create(types.recursive, node.size, cid, cb), + ({ node, cid }, cb) => { + try { + cb(null, new DAGLink(types.recursive, node.size, cid)) + } catch (err) { + cb(err) + } + }, (link, cb) => { rLink = link; cb(null) } ], cb), // the pin-set nodes link to a special 'empty' node, so make sure it exists - cb => DAGNode.create(Buffer.alloc(0), (err, empty) => { - if (err) { return cb(err) } + cb => { + let empty + + try { + empty = DAGNode.create(Buffer.alloc(0)) + } catch (err) { + return cb(err) + } + dag.put(empty, { version: 0, - hashAlg: 'sha2-256', - format: 'dag-pb', + format: multicodec.DAG_PB, + hashAlg: multicodec.SHA2_256, preload: false }, cb) - }), + }, // create a root node with DAGLinks to the direct and recursive DAGs - cb => DAGNode.create(Buffer.alloc(0), [dLink, rLink], (err, node) => { - if (err) { return cb(err) } + cb => { + let node + + try { + node = DAGNode.create(Buffer.alloc(0), [dLink, rLink]) + } catch (err) { + return cb(err) + } + root = node dag.put(root, { version: 0, - hashAlg: 'sha2-256', - format: 'dag-pb', + format: multicodec.DAG_PB, + hashAlg: multicodec.SHA2_256, preload: false }, (err, cid) => { if (!err) { @@ -125,7 +154,7 @@ module.exports = (self) => { } cb(err) }) - }), + }, // hack for CLI tests cb => repo.closed ? repo.open(cb) : cb(null, null), diff --git a/src/core/components/resolve.js b/src/core/components/resolve.js index 1ca80e8249..db9039551e 100644 --- a/src/core/components/resolve.js +++ b/src/core/components/resolve.js @@ -3,12 +3,11 @@ const promisify = require('promisify-es6') const isIpfs = require('is-ipfs') const setImmediate = require('async/setImmediate') -const doUntil = require('async/doUntil') const CID = require('cids') const { cidToString } = require('../../utils/cid') module.exports = (self) => { - return promisify((name, opts, cb) => { + return promisify(async (name, opts, cb) => { if (typeof opts === 'function') { cb = opts opts = {} @@ -17,7 +16,7 @@ module.exports = (self) => { opts = opts || {} if (!isIpfs.path(name)) { - return setImmediate(() => cb(new Error('invalid argument'))) + return setImmediate(() => cb(new Error('invalid argument ' + name))) } // TODO remove this and update subsequent code when IPNS is implemented @@ -34,56 +33,32 @@ module.exports = (self) => { const path = split.slice(3).join('/') - resolve(cid, path, (err, res) => { - if (err) return cb(err) - const { cid, remainderPath } = res - cb(null, `/ipfs/${cidToString(cid, { base: opts.cidBase })}${remainderPath ? '/' + remainderPath : ''}`) - }) - }) - - // Resolve the given CID + path to a CID. - function resolve (cid, path, callback) { - let value, remainderPath - doUntil( - (cb) => { - self.block.get(cid, (err, block) => { - if (err) return cb(err) - - const r = self._ipld.resolvers[cid.codec] + const results = self._ipld.resolve(cid, path) + let value = cid + let remainderPath = path + try { + for await (const result of results) { + if (result.remainderPath === '') { + // Use values from previous iteration if the value isn't a CID + if (CID.isCID(result.value)) { + value = result.value + remainderPath = '' + } - if (!r) { - return cb(new Error(`No resolver found for codec "${cid.codec}"`)) + if (result.value && CID.isCID(result.value.Hash)) { + value = result.value.Hash + remainderPath = '' } - r.resolver.resolve(block.data, path, (err, result) => { - if (err) return cb(err) - value = result.value - remainderPath = result.remainderPath - cb() - }) - }) - }, - () => { - if (value && value['/']) { - // If we've hit a CID, replace the current CID. - cid = new CID(value['/']) - path = remainderPath - } else if (CID.isCID(value)) { - // If we've hit a CID, replace the current CID. - cid = value - path = remainderPath - } else { - // We've hit a value. Return the current CID and the remaining path. - return true + break } - // Continue resolving unless the path is empty. - return !path || path === '/' - }, - (err) => { - if (err) return callback(err) - callback(null, { cid, remainderPath: path }) + value = result.value + remainderPath = result.remainderPath } - ) - } + } catch (error) { + return cb(error) + } + return cb(null, `/ipfs/${cidToString(value, { base: opts.cidBase })}${remainderPath ? '/' + remainderPath : ''}`) + }) } diff --git a/src/core/runtime/ipld-nodejs.js b/src/core/runtime/ipld-nodejs.js index aa2172fe82..0a26ac1c75 100644 --- a/src/core/runtime/ipld-nodejs.js +++ b/src/core/runtime/ipld-nodejs.js @@ -1,39 +1,37 @@ 'use strict' const mergeOptions = require('merge-options') -const ipldDagCbor = require('ipld-dag-cbor') -const ipldDagPb = require('ipld-dag-pb') -const ipldRaw = require('ipld-raw') +const multicodec = require('multicodec') // All known (non-default) IPLD formats const IpldFormats = { - get 'bitcoin-block' () { + get [multicodec.BITCOIN_BLOCK] () { return require('ipld-bitcoin') }, - get 'eth-account-snapshot' () { + get [multicodec.ETH_ACCOUNT_SNAPSHOT] () { return require('ipld-ethereum').ethAccountSnapshot }, - get 'eth-block' () { + get [multicodec.ETH_BLOCK] () { return require('ipld-ethereum').ethBlock }, - get 'eth-block-list' () { + get [multicodec.ETH_BLOCK_LIST] () { return require('ipld-ethereum').ethBlockList }, - get 'eth-state-trie' () { + get [multicodec.ETH_STATE_TRIE] () { return require('ipld-ethereum').ethStateTrie }, - get 'eth-storage-trie' () { + get [multicodec.ETH_STORAGE_TRIE] () { return require('ipld-ethereum').ethStorageTrie }, - get 'eth-tx' () { + get [multicodec.ETH_TX] () { return require('ipld-ethereum').ethTx }, - get 'eth-tx-trie' () { + get [multicodec.ETH_TX_TRIE] () { return require('ipld-ethereum').ethTxTrie }, - get 'git-raw' () { + get [multicodec.GIT_RAW] () { return require('ipld-git') }, - get 'zcash-block' () { + get [multicodec.ZCASH_BLOCK] () { return require('ipld-zcash') } } @@ -44,11 +42,13 @@ module.exports = (blockService, options = {}, log) => { { concatArrays: true }, { blockService: blockService, - formats: [ipldDagCbor, ipldDagPb, ipldRaw], - loadFormat: (codec, callback) => { + loadFormat: (codec) => { log('Loading IPLD format', codec) - if (IpldFormats[codec]) return callback(null, IpldFormats[codec]) - callback(new Error(`Missing IPLD format "${codec}"`)) + if (IpldFormats[codec]) { + return IpldFormats[codec] + } else { + throw new Error(`Missing IPLD format "${codec}"`) + } } }, options) } diff --git a/src/core/utils.js b/src/core/utils.js index 96db3a9c87..98760b0338 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -124,14 +124,13 @@ const resolvePath = promisify(function (objectAPI, ipfsPaths, callback) { } const linkName = links[0] - const nextObj = obj.links.find(link => link.name === linkName) + const nextObj = obj.Links.find(link => link.Name === linkName) + if (!nextObj) { - return cb(new Error( - `no link named "${linkName}" under ${cid.toBaseEncodedString()}` - )) + return cb(new Error(`no link named "${linkName}" under ${cid}`)) } - objectAPI.get(nextObj.cid, follow.bind(null, nextObj.cid, links.slice(1))) + objectAPI.get(nextObj.Hash, follow.bind(null, nextObj.Hash, links.slice(1))) } }, callback) }) diff --git a/src/http/api/resources/dag.js b/src/http/api/resources/dag.js index eaed94bdda..d636efb8fa 100644 --- a/src/http/api/resources/dag.js +++ b/src/http/api/resources/dag.js @@ -1,11 +1,11 @@ 'use strict' -const promisify = require('promisify-es6') const CID = require('cids') const multipart = require('ipfs-multipart') const mh = require('multihashes') const Joi = require('@hapi/joi') const multibase = require('multibase') +const multicodec = require('multicodec') const Boom = require('boom') const debug = require('debug') const { @@ -109,8 +109,14 @@ exports.get = { throw Boom.badRequest(err) } + let value = result.value + + if (!Buffer.isBuffer(result.value) && result.value.toJSON) { + value = result.value.toJSON() + } + try { - result.value = encodeBufferKeys(result.value, dataEncoding) + result.value = encodeBufferKeys(value, dataEncoding) } catch (err) { throw Boom.boomify(err) } @@ -126,7 +132,7 @@ exports.put = { 'input-enc': Joi.string().default('json'), pin: Joi.boolean(), hash: Joi.string().valid(Object.keys(mh.names)).default('sha2-256'), - 'cid-base': Joi.string().valid(multibase.names).default('base58btc') + 'cid-base': Joi.string().valid(multibase.names) }).unknown() }, @@ -173,15 +179,11 @@ exports.put = { } } else { const { ipfs } = request.server.app - const codec = ipfs._ipld.resolvers[format] - - if (!codec) { - throw Boom.badRequest(`Missing IPLD format "${request.query.format}"`) - } - - const deserialize = promisify(codec.util.deserialize) - node = await deserialize(data) + // IPLD expects the format and hashAlg as constants + const codecConstant = format.toUpperCase().replace(/-/g, '_') + const ipldFormat = await ipfs._ipld._getFormat(multicodec[codecConstant]) + node = await ipldFormat.util.deserialize(data) } return { @@ -242,28 +244,17 @@ exports.resolve = { let lastCid = ref let lastRemainderPath = path - while (true) { - const block = await ipfs.block.get(lastCid) - const codec = ipfs._ipld.resolvers[lastCid.codec] + if (path) { + const result = ipfs._ipld.resolve(lastCid, path) + while (true) { + const resolveResult = (await result.next()).value + if (!CID.isCID(resolveResult.value)) { + break + } - if (!codec) { - throw Boom.badRequest(`Missing IPLD format "${lastCid.codec}"`) + lastRemainderPath = resolveResult.remainderPath + lastCid = resolveResult.value } - - const resolve = promisify(codec.resolver.resolve) - const res = await resolve(block.data, lastRemainderPath) - - if (!res.remainderPath) { - break - } - - lastRemainderPath = res.remainderPath - - if (!CID.isCID(res.value)) { - break - } - - lastCid = res.value } return h.response({ diff --git a/src/http/api/resources/files-regular.js b/src/http/api/resources/files-regular.js index b2459bf0a8..7175b17972 100644 --- a/src/http/api/resources/files-regular.js +++ b/src/http/api/resources/files-regular.js @@ -90,7 +90,7 @@ exports.cat = { return pusher.end(err) } - err.message = err.message === 'No such file' + err.message = err.message === 'file does not exist' ? err.message : 'Failed to cat file: ' + err diff --git a/src/http/api/resources/object.js b/src/http/api/resources/object.js index 6480141510..bb55ac6938 100644 --- a/src/http/api/resources/object.js +++ b/src/http/api/resources/object.js @@ -1,13 +1,9 @@ 'use strict' -const promisify = require('promisify-es6') const CID = require('cids') const multipart = require('ipfs-multipart') const dagPB = require('ipld-dag-pb') const { DAGNode, DAGLink } = dagPB -const calculateCid = promisify(dagPB.util.cid) -const deserialize = promisify(dagPB.util.deserialize) -const createDagNode = promisify(DAGNode.create) const Joi = require('@hapi/joi') const multibase = require('multibase') const Boom = require('boom') @@ -87,7 +83,7 @@ exports.get = { let node, cid try { node = await ipfs.object.get(key, { enc: enc }) - cid = await calculateCid(node) + cid = await dagPB.util.cid(dagPB.util.serialize(node)) } catch (err) { throw Boom.boomify(err, { message: 'Failed to get object' }) } @@ -145,7 +141,7 @@ exports.put = { if (enc === 'protobuf') { try { - return { node: await deserialize(data) } + return { node: await dagPB.util.deserialize(data) } } catch (err) { throw Boom.badRequest('Failed to deserialize: ' + err) } @@ -159,7 +155,7 @@ exports.put = { } try { - return { node: await createDagNode(nodeJson.Data, nodeJson.Links) } + return { node: DAGNode.create(nodeJson.Data, nodeJson.Links) } } catch (err) { throw Boom.badRequest('Failed to create DAG node: ' + err) } @@ -258,26 +254,22 @@ exports.links = { async handler (request, h) { const { ipfs } = request.server.app const { key } = request.pre.args - - let node - try { - node = await ipfs.object.get(key) - } catch (err) { - throw Boom.boomify(err, { message: 'Failed to get object links' }) + const response = { + Hash: cidToString(key, { base: request.query['cid-base'], upgrade: false }) } + const links = await ipfs.object.links(key) - const nodeJSON = node.toJSON() - - return h.response({ - Hash: cidToString(key, { base: request.query['cid-base'], upgrade: false }), - Links: nodeJSON.links.map((l) => { + if (links) { + response.Links = links.map((l) => { return { - Name: l.name, - Size: l.size, - Hash: cidToString(l.cid, { base: request.query['cid-base'], upgrade: false }) + Name: l.Name, + Size: l.Tsize, + Hash: cidToString(l.Hash, { base: request.query['cid-base'], upgrade: false }) } }) - }) + } + + return h.response(response) } } diff --git a/src/http/gateway/resources/gateway.js b/src/http/gateway/resources/gateway.js index fda0610287..8f538aa22c 100644 --- a/src/http/gateway/resources/gateway.js +++ b/src/http/gateway/resources/gateway.js @@ -82,7 +82,7 @@ module.exports = { // found index file // redirect to URL/ - return h.redirect(PathUtils.joinURLParts(ref, data[0].name)) + return h.redirect(PathUtils.joinURLParts(ref, data[0].Name)) case (errorToString.startsWith('Error: no link named')): throw Boom.boomify(err, { statusCode: 404 }) case (errorToString.startsWith('Error: multihash length inconsistent')): diff --git a/src/utils/cid.js b/src/utils/cid.js index adf16963d0..657815218f 100644 --- a/src/utils/cid.js +++ b/src/utils/cid.js @@ -19,7 +19,6 @@ const CID = require('cids') */ exports.cidToString = (cid, options) => { options = options || {} - options.base = options.base || null options.upgrade = options.upgrade !== false if (!CID.isCID(cid)) { diff --git a/test/cli/block.js b/test/cli/block.js index 940aeb6bff..8de1be03f3 100644 --- a/test/cli/block.js +++ b/test/cli/block.js @@ -23,7 +23,7 @@ describe('block', () => runOnAndOff((thing) => { return ipfs('block put --format eth-block --mhtype keccak-256 test/fixtures/test-data/eth-block') .then((out) => - expect(out).to.eql('z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS\n')) + expect(out).to.eql('bagiacgzarkhijr4xmbp345ovwwxra7kcecrnwcwtl7lg3g7d2ogyprdswjwq\n')) }) it('should put and print CID encoded in specified base', function () { diff --git a/test/cli/dag.js b/test/cli/dag.js index 9cd6a3a586..0c7147ec2a 100644 --- a/test/cli/dag.js +++ b/test/cli/dag.js @@ -3,6 +3,7 @@ const expect = require('chai').expect const runOnAndOff = require('../utils/on-and-off') +const path = require('path') describe('dag', () => runOnAndOff.off((thing) => { let ipfs @@ -15,10 +16,10 @@ describe('dag', () => runOnAndOff.off((thing) => { this.timeout(20 * 1000) // put test eth-block - return ipfs('block put --format eth-block --mhtype keccak-256 test/fixtures/test-data/eth-block').then((out) => { - expect(out).to.eql('z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS\n') + return ipfs(`block put --format eth-block --mhtype keccak-256 ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/eth-block`).then((out) => { + expect(out).to.eql('bagiacgzarkhijr4xmbp345ovwwxra7kcecrnwcwtl7lg3g7d2ogyprdswjwq\n') // lookup path on eth-block - return ipfs('dag get z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS/parentHash') + return ipfs('dag get bagiacgzarkhijr4xmbp345ovwwxra7kcecrnwcwtl7lg3g7d2ogyprdswjwq/parentHash') }).then((out) => { let expectHash = Buffer.from('c8c0a17305adea9bbb4b98a52d44f0c1478f5c48fc4b64739ee805242501b256', 'hex') expect(out).to.be.eql('0x' + expectHash.toString('hex') + '\n') diff --git a/test/cli/dht.js b/test/cli/dht.js index 45f13cadc3..f772ebc6af 100644 --- a/test/cli/dht.js +++ b/test/cli/dht.js @@ -9,14 +9,14 @@ chai.use(dirtyChai) const series = require('async/series') const parallel = require('async/parallel') - +const path = require('path') const DaemonFactory = require('ipfsd-ctl') const df = DaemonFactory.create({ type: 'js' }) const ipfsExec = require('../utils/ipfs-exec') const daemonOpts = { - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config: { Bootstrap: [], Discovery: { diff --git a/test/cli/files.js b/test/cli/files.js index e9a6c69422..b73760c8e0 100644 --- a/test/cli/files.js +++ b/test/cli/files.js @@ -223,7 +223,7 @@ describe('files', () => runOnAndOff((thing) => { return ipfs('add test/fixtures/less-than-default-max-chunk-size --cid-version=1') .then((out) => { expect(out) - .to.eql('added zb2rhh5LdXumxQfNZCqV8pmcC56LX71ERgf2qCNQsmZnwYYx9 less-than-default-max-chunk-size\n') + .to.eql('added bafkreie3abdlmy7dtxddm4vkbhd2x2yax5scf4m35eyxf3ywj2uwkjbhgi less-than-default-max-chunk-size\n') }) }) @@ -233,7 +233,7 @@ describe('files', () => runOnAndOff((thing) => { return ipfs('add test/fixtures/greater-than-default-max-chunk-size --cid-version=1') .then((out) => { expect(out) - .to.eql('added zdj7We8b7taMubqinMgnZ9HFUiv17bm5zjJkYnqpfxXhqx5sY greater-than-default-max-chunk-size\n') + .to.eql('added bafybeiebjiahgamnil3r3os2hqorjualrgx6hpqh5zuqbhjmt7tyjqqttm greater-than-default-max-chunk-size\n') }) }) @@ -243,7 +243,7 @@ describe('files', () => runOnAndOff((thing) => { return ipfs(`add test/fixtures/less-than-default-max-chunk-size --cid-version=1 --raw-leaves=false`) .then((out) => { expect(out) - .to.eql('added zdj7WWPWpmpFkrWJBhUEZ4QkGumsFsEdkaaEGs7U4dzJraogp less-than-default-max-chunk-size\n') + .to.eql('added bafybeiaoh5okvpnuhndsz4kgdhulnkm566rz7w7il6r2zm6wxu5f5uqlsu less-than-default-max-chunk-size\n') }) }) @@ -253,7 +253,7 @@ describe('files', () => runOnAndOff((thing) => { return ipfs(`add test/fixtures/greater-than-default-max-chunk-size --cid-version=1 --raw-leaves=false`) .then((out) => { expect(out) - .to.eql('added zdj7WW4sSVxNKLJXQSzy3RD7msG3SS4WgdGEdJzDZ7swYv65p greater-than-default-max-chunk-size\n') + .to.eql('added bafybeiajpcrr2qglyeq3biilzt25ty6kpjs7huy2lfxopqfke6riaaxnim greater-than-default-max-chunk-size\n') }) }) @@ -263,7 +263,7 @@ describe('files', () => runOnAndOff((thing) => { return ipfs('add test/fixtures/less-than-default-max-chunk-size --cid-version=1 --raw-leaves=true') .then((out) => { expect(out) - .to.eql('added zb2rhh5LdXumxQfNZCqV8pmcC56LX71ERgf2qCNQsmZnwYYx9 less-than-default-max-chunk-size\n') + .to.eql('added bafkreie3abdlmy7dtxddm4vkbhd2x2yax5scf4m35eyxf3ywj2uwkjbhgi less-than-default-max-chunk-size\n') }) }) @@ -273,7 +273,7 @@ describe('files', () => runOnAndOff((thing) => { return ipfs('add test/fixtures/greater-than-default-max-chunk-size --cid-version=1 --raw-leaves=true') .then((out) => { expect(out) - .to.eql('added zdj7We8b7taMubqinMgnZ9HFUiv17bm5zjJkYnqpfxXhqx5sY greater-than-default-max-chunk-size\n') + .to.eql('added bafybeiebjiahgamnil3r3os2hqorjualrgx6hpqh5zuqbhjmt7tyjqqttm greater-than-default-max-chunk-size\n') }) }) diff --git a/test/cli/name-pubsub.js b/test/cli/name-pubsub.js index fd125948a5..fef64295de 100644 --- a/test/cli/name-pubsub.js +++ b/test/cli/name-pubsub.js @@ -6,7 +6,7 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const parallel = require('async/parallel') const series = require('async/series') const ipfsExec = require('../utils/ipfs-exec') @@ -19,7 +19,7 @@ const emptyDirCid = 'QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn' const spawnDaemon = (callback) => { df.spawn({ - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), args: ['--enable-namesys-pubsub'], initOptions: { bits: 512 }, config: { @@ -171,7 +171,7 @@ describe('name-pubsub', () => { before(function (done) { this.timeout(50 * 1000) - ipfsA('add src/init-files/init-docs/readme') + ipfsA(`add ${path.resolve(`${__dirname}/../../src/init-files/init-docs/readme`)}`) .then((out) => { cidAdded = out.split(' ')[1] done() @@ -225,7 +225,7 @@ describe('name-pubsub', () => { this.timeout(80 * 1000) df.spawn({ - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config: {}, initOptions: { bits: 512 } }, (err, node) => { diff --git a/test/cli/name.js b/test/cli/name.js index c34ae70ef4..1c0638503f 100644 --- a/test/cli/name.js +++ b/test/cli/name.js @@ -6,7 +6,7 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const hat = require('hat') const ipfsExec = require('../utils/ipfs-exec') @@ -32,7 +32,7 @@ describe('name', () => { this.timeout(80 * 1000) df.spawn({ - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config: { Bootstrap: [] }, @@ -56,7 +56,7 @@ describe('name', () => { expect(id).to.have.property('id') nodeId = id.id - return ipfs('add src/init-files/init-docs/readme') + return ipfs(`add ${path.resolve(`${__dirname}/../../src/init-files/init-docs/readme`)}`) }) .then((out) => { cidAdded = out.split(' ')[1] @@ -197,7 +197,7 @@ describe('name', () => { this.timeout(80 * 1000) df.spawn({ - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config: { Bootstrap: [], Discovery: { @@ -229,7 +229,7 @@ describe('name', () => { expect(id).to.have.property('id') nodeId = id.id - return ipfs('add src/init-files/init-docs/readme') + return ipfs(`add ${path.resolve(`${__dirname}/../../src/init-files/init-docs/readme`)}`) }) .then((out) => { cidAdded = out.split(' ')[1] diff --git a/test/cli/object.js b/test/cli/object.js index ceb9f24627..efaaf6cc5e 100644 --- a/test/cli/object.js +++ b/test/cli/object.js @@ -56,7 +56,7 @@ describe('object', () => runOnAndOff((thing) => { return ipfs('object new') .then((out) => out.trim()) - .then((hash) => ipfs(`object patch set-data ${hash} test/fixtures/test-data/hello`)) + .then((hash) => ipfs(`object patch set-data ${hash} ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/hello`)) .then((out) => out.trim()) .then((hash) => ipfs(`object get ${hash}`)) .then((out) => { @@ -70,7 +70,7 @@ describe('object', () => runOnAndOff((thing) => { return ipfs('object new') .then((out) => out.trim()) - .then((hash) => ipfs(`object patch set-data ${hash} test/fixtures/test-data/hello`)) + .then((hash) => ipfs(`object patch set-data ${hash} ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/hello`)) .then((out) => out.trim()) .then((hash) => ipfs(`object get --data-encoding=utf8 ${hash}`)) .then((out) => { @@ -80,7 +80,7 @@ describe('object', () => runOnAndOff((thing) => { }) it('should get and print CIDs encoded in specified base', () => { - return ipfs('add test/fixtures/planets -r --cid-version=1') + return ipfs(`add ${path.resolve(path.join(__dirname, '..'))}/fixtures/planets -r --cid-version=1`) .then(out => { const lines = out.trim().split('\n') return lines[lines.length - 1].split(' ')[1] @@ -96,7 +96,7 @@ describe('object', () => runOnAndOff((thing) => { }) it('put', () => { - return ipfs('object put test/fixtures/test-data/node.json').then((out) => { + return ipfs(`object put ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/node.json`).then((out) => { expect(out).to.eql( 'added QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm\n' ) @@ -105,7 +105,7 @@ describe('object', () => runOnAndOff((thing) => { // TODO: unskip after switch to v1 CIDs by default it.skip('should put and print CID encoded in specified base', () => { - return ipfs('object put test/fixtures/test-data/node.json --cid-base=base64') + return ipfs(`object put ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/node.json --cid-base=base64`) .then((out) => { expect(out).to.eql( 'added mAXASIKbM02Neyt6L1RRLYVEOuNlqDOzTvBboo3cI/u6f/+Vk\n' @@ -163,7 +163,7 @@ describe('object', () => runOnAndOff((thing) => { }) it('should get links and print CIDs encoded in specified base', () => { - return ipfs('add test/fixtures/planets -r --cid-version=1') + return ipfs(`add ${path.resolve(path.join(__dirname, '..'))}/fixtures/planets -r --cid-version=1`) .then(out => { const lines = out.trim().split('\n') return lines[lines.length - 1].split(' ')[1] @@ -180,8 +180,12 @@ describe('object', () => runOnAndOff((thing) => { describe('patch', function () { this.timeout(40 * 1000) + before(async () => { + await ipfs('object new') + }) + it('append-data', () => { - return ipfs('object patch append-data QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n test/fixtures/test-data/badconfig').then((out) => { + return ipfs(`object patch append-data QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/badconfig`).then((out) => { expect(out).to.eql( 'QmfY37rjbPCZRnhvvJuQ46htW3VCAWziVB991P79h6WSv6\n' ) @@ -190,7 +194,7 @@ describe('object', () => runOnAndOff((thing) => { // TODO: unskip after switch to v1 CIDs by default it.skip('should append-data and print CID encoded in specified base', () => { - return ipfs('object patch append-data QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n test/fixtures/test-data/badconfig --cid-base=base64').then((out) => { + return ipfs(`object patch append-data QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/badconfig --cid-base=base64`).then((out) => { expect(out).to.eql( 'mAXASIP+BZ7jGtaTyLGOs0xYcQvH7K9kVKEbyzXAkwLoZwrRj\n' ) @@ -198,7 +202,7 @@ describe('object', () => runOnAndOff((thing) => { }) it('set-data', () => { - return ipfs('object patch set-data QmfY37rjbPCZRnhvvJuQ46htW3VCAWziVB991P79h6WSv6 test/fixtures/test-data/badconfig').then((out) => { + return ipfs(`object patch set-data QmfY37rjbPCZRnhvvJuQ46htW3VCAWziVB991P79h6WSv6 ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/badconfig`).then((out) => { expect(out).to.eql( 'QmfY37rjbPCZRnhvvJuQ46htW3VCAWziVB991P79h6WSv6\n' ) @@ -207,7 +211,7 @@ describe('object', () => runOnAndOff((thing) => { // TODO: unskip after switch to v1 CIDs by default it.skip('should set-data and print CID encoded in specified base', () => { - return ipfs('object patch set-data QmfY37rjbPCZRnhvvJuQ46htW3VCAWziVB991P79h6WSv6 test/fixtures/test-data/badconfig --cid-base=base64').then((out) => { + return ipfs(`object patch set-data QmfY37rjbPCZRnhvvJuQ46htW3VCAWziVB991P79h6WSv6 ${path.resolve(path.join(__dirname, '..'))}/fixtures/test-data/badconfig --cid-base=base64`).then((out) => { expect(out).to.eql( 'mAXASIP+BZ7jGtaTyLGOs0xYcQvH7K9kVKEbyzXAkwLoZwrRj\n' ) diff --git a/test/cli/pin.js b/test/cli/pin.js index 5313e3dbd3..15458c12cb 100644 --- a/test/cli/pin.js +++ b/test/cli/pin.js @@ -5,13 +5,15 @@ const expect = require('chai').expect const CID = require('cids') const runOnAndOff = require('../utils/on-and-off') +const path = require('path') // fixture structure: // planets/ // solar-system.md // mercury/ // wiki.md -const fixturePath = 'test/fixtures/planets' +const fixturePath = path.resolve(path.join(__dirname, '..'), 'fixtures/planets') + const pins = { root: 'QmTAMavb995EHErSrKo7mB8dYkpaSJxu6ys1a6XJyB2sys', solarWiki: 'QmTMbkDfvHwq3Aup6Nxqn3KKw9YnoKzcZvuArAfQ9GF3QG', diff --git a/test/cli/ping.js b/test/cli/ping.js index 170a1fc3b9..05d9b709ab 100644 --- a/test/cli/ping.js +++ b/test/cli/ping.js @@ -7,7 +7,7 @@ const dirtyChai = require('dirty-chai') const series = require('async/series') const DaemonFactory = require('ipfsd-ctl') const ipfsExec = require('../utils/ipfs-exec') - +const path = require('path') const df = DaemonFactory.create({ type: 'js' }) const expect = chai.expect chai.use(dirtyChai) @@ -35,7 +35,7 @@ describe('ping', function () { series([ (cb) => { df.spawn({ - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config, initOptions: { bits: 512 } }, (err, _ipfsd) => { @@ -59,7 +59,7 @@ describe('ping', function () { this.timeout(60 * 1000) df.spawn({ - exec: './src/cli/bin.js', + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config, initoptions: { bits: 512 } }, (err, _ipfsd) => { diff --git a/test/cli/pubsub.js b/test/cli/pubsub.js index b80eed7f09..fcc231331c 100644 --- a/test/cli/pubsub.js +++ b/test/cli/pubsub.js @@ -10,7 +10,7 @@ const delay = require('delay') const series = require('async/series') const ipfsExec = require('../utils/ipfs-exec') const IPFS = require('../../src') - +const path = require('path') const DaemonFactory = require('ipfsd-ctl') const df = DaemonFactory.create({ type: 'js' }) @@ -61,7 +61,7 @@ describe('pubsub', function () { df.spawn({ initOptions: { bits: 512 }, args: ['--enable-pubsub-experiment'], - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config }, (err, _ipfsd) => { expect(err).to.not.exist() diff --git a/test/cli/resolve.js b/test/cli/resolve.js index 3aa7bcb70c..190eba0c66 100644 --- a/test/cli/resolve.js +++ b/test/cli/resolve.js @@ -16,7 +16,7 @@ describe('resolve', () => runOnAndOff((thing) => { }) it('should resolve an IPFS hash', () => { - const filePath = path.join(process.cwd(), '/src/init-files/init-docs/readme') + const filePath = path.join(path.resolve(__dirname, '..', '..'), 'src/init-files/init-docs/readme') let hash return ipfs(`add ${filePath}`) @@ -33,7 +33,7 @@ describe('resolve', () => runOnAndOff((thing) => { it('should resolve an IPFS hash and print CID encoded in specified base', function () { this.timeout(10 * 1000) - const filePath = path.join(process.cwd(), '/src/init-files/init-docs/readme') + const filePath = path.join(path.resolve(__dirname, '..', '..'), 'src/init-files/init-docs/readme') let b58Hash let b64Hash @@ -52,7 +52,7 @@ describe('resolve', () => runOnAndOff((thing) => { it('should resolve an IPFS path link', function () { this.timeout(10 * 1000) - const filePath = path.join(process.cwd(), '/src/init-files/init-docs/readme') + const filePath = path.join(path.resolve(__dirname, '..', '..'), 'src/init-files/init-docs/readme') let fileHash, rootHash return ipfs(`add ${filePath} --wrap-with-directory`) diff --git a/test/cli/swarm.js b/test/cli/swarm.js index 889b309681..805bd1affe 100644 --- a/test/cli/swarm.js +++ b/test/cli/swarm.js @@ -8,7 +8,7 @@ const expect = chai.expect chai.use(dirtyChai) const series = require('async/series') const ipfsExec = require('../utils/ipfs-exec') - +const path = require('path') const parallel = require('async/parallel') const DaemonFactory = require('ipfsd-ctl') @@ -37,7 +37,7 @@ describe('swarm', () => { series([ (cb) => { df.spawn({ - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config, initOptions: { bits: 512 } }, (err, node) => { @@ -49,7 +49,7 @@ describe('swarm', () => { }, (cb) => { df.spawn({ - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config, initOptions: { bits: 512 } }, (err, node) => { diff --git a/test/core/bitswap.spec.js b/test/core/bitswap.spec.js index b3261d4d88..e5bce37387 100644 --- a/test/core/bitswap.spec.js +++ b/test/core/bitswap.spec.js @@ -15,7 +15,7 @@ const multiaddr = require('multiaddr') const isNode = require('detect-node') const multihashing = require('multihashing-async') const CID = require('cids') - +const path = require('path') const IPFSFactory = require('ipfsd-ctl') const IPFS = require('../../src/core') @@ -64,7 +64,7 @@ let nodes = [] function addNode (fDaemon, inProcNode, callback) { fDaemon.spawn({ - exec: './src/cli/bin.js', + exec: isNode ? path.resolve(`${__dirname}/../../src/cli/bin.js`) : './src/cli/bin.js', initOptions: { bits: 512 }, config: { Addresses: { diff --git a/test/core/files.spec.js b/test/core/files.spec.js index 77f99739ca..6570480006 100644 --- a/test/core/files.spec.js +++ b/test/core/files.spec.js @@ -91,7 +91,7 @@ describe('files', () => { }, (err, files) => { expect(err).to.not.exist() expect(files.length).to.equal(1) - expect(files[0].hash).to.equal('zb2rhiNedvrkpYhcrgtpmhKk5UPzcgizgSXaQLYXNY745BmYP') + expect(files[0].hash).to.equal('bafkreifojmzibzlof6xyh5auu3r5vpu5l67brf3fitaf73isdlglqw2t7q') expect(files[0].size).to.equal(3) done() }) @@ -104,7 +104,7 @@ describe('files', () => { }, (err, files) => { expect(err).to.not.exist() expect(files.length).to.equal(1) - expect(files[0].hash).to.equal('zdj7WcDSFNSsZkdkbpSDGeLsBtHbYKyvPQsaw6PpeeYdGqoAx') + expect(files[0].hash).to.equal('bafybeide2caf5we5a7izifzwzz5ds2gla67vsfgrzvbzpnyyirnfzgwf5e') expect(files[0].size).to.equal(11) done() }) diff --git a/test/core/init.spec.js b/test/core/init.spec.js index 62372c48c0..797cbced03 100644 --- a/test/core/init.spec.js +++ b/test/core/init.spec.js @@ -84,7 +84,7 @@ describe('init', () => { ipfs.object.get(multihash, { enc: 'base58' }, (err, node) => { expect(err).to.not.exist() - expect(node.links).to.exist() + expect(node.Links).to.exist() done() }) }) diff --git a/test/core/kad-dht.node.js b/test/core/kad-dht.node.js index 1d7452c596..d07be33f20 100644 --- a/test/core/kad-dht.node.js +++ b/test/core/kad-dht.node.js @@ -6,7 +6,7 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const parallel = require('async/parallel') const IPFSFactory = require('ipfsd-ctl') @@ -26,7 +26,7 @@ const config = { function createNode (callback) { f.spawn({ - exec: './src/cli/bin.js', + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), config, initOptions: { bits: 512 } }, callback) diff --git a/test/core/object.spec.js b/test/core/object.spec.js index eaac7b35a8..8719413d73 100644 --- a/test/core/object.spec.js +++ b/test/core/object.spec.js @@ -120,9 +120,9 @@ describe('object', () => { nodeAWithLink: ['nodeA', 'nodeB', (res, cb) => { waterfall([ (done) => ipfs.object.patch.addLink(res.nodeA.cid, { - name: res.nodeB.node.name, - multihash: res.nodeB.cid, - size: res.nodeB.node.size + Name: 'nodeBLink', + Hash: res.nodeB.cid, + Tsize: res.nodeB.node.size }, done), (cid, done) => ipfs.object.get(cid, (err, node) => done(err, { node, cid })) ], cb) @@ -130,7 +130,7 @@ describe('object', () => { }, (err, res) => { expect(err).to.not.exist() - const link = res.nodeAWithLink.node.links[0] + const link = res.nodeAWithLink.node.Links[0] ipfs.object.patch.rmLink(res.nodeAWithLink.cid, link, null, (err) => { expect(err).to.not.exist() done() diff --git a/test/core/pin-set.js b/test/core/pin-set.js index c1a31a1319..088d248a12 100644 --- a/test/core/pin-set.js +++ b/test/core/pin-set.js @@ -11,7 +11,8 @@ const parallelLimit = require('async/parallelLimit') const series = require('async/series') const { util: { - cid + cid, + serialize }, DAGNode } = require('ipld-dag-pb') @@ -35,7 +36,7 @@ function createNodes (num, callback) { const items = [] for (let i = 0; i < num; i++) { items.push(cb => - createNode(String(i), (err, res) => cb(err, res.cid.toBaseEncodedString())) + createNode(String(i), (err, res) => cb(err, !err && res.cid.toBaseEncodedString())) ) } @@ -48,18 +49,20 @@ function createNode (data, links = [], callback) { links = [] } - DAGNode.create(data, links, (err, node) => { - if (err) { - return callback(err) - } + let node - cid(node, (err, result) => { - callback(err, { - node, - cid: result - }) + try { + node = DAGNode.create(data, links) + } catch (err) { + return callback(err) + } + + cid(serialize(node), { cidVersion: 0 }).then(cid => { + callback(null, { + node, + cid }) - }) + }, err => callback(err)) } describe('pinSet', function () { @@ -104,10 +107,10 @@ describe('pinSet', function () { pinSet.storeSet([nodeHash], (err, rootNode) => { expect(err).to.not.exist() expect(rootNode.cid.toBaseEncodedString()).to.eql(expectedRootHash) - expect(rootNode.node.links).to.have.length(defaultFanout + 1) + expect(rootNode.node.Links).to.have.length(defaultFanout + 1) - const lastLink = rootNode.node.links[rootNode.node.links.length - 1] - const mhash = lastLink.cid.toBaseEncodedString() + const lastLink = rootNode.node.Links[rootNode.node.Links.length - 1] + const mhash = lastLink.Hash.toBaseEncodedString() expect(mhash).to.eql(nodeHash) done() }) @@ -126,7 +129,7 @@ describe('pinSet', function () { expect(err).to.not.exist() expect(result.node.size).to.eql(3184696) - expect(result.node.links).to.have.length(defaultFanout) + expect(result.node.Links).to.have.length(defaultFanout) expect(result.cid.toBaseEncodedString()).to.eql(expectedHash) pinSet.loadSet(result.node, '', (err, loaded) => { diff --git a/test/core/ping.spec.js b/test/core/ping.spec.js index 3b477e05ee..6d04792013 100644 --- a/test/core/ping.spec.js +++ b/test/core/ping.spec.js @@ -9,10 +9,10 @@ const parallel = require('async/parallel') const series = require('async/series') const DaemonFactory = require('ipfsd-ctl') const isNode = require('detect-node') - +const path = require('path') const expect = chai.expect chai.use(dirtyChai) -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const df = DaemonFactory.create({ exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) }) const dfProc = DaemonFactory.create({ exec: require('../../'), type: 'proc' diff --git a/test/core/preload.spec.js b/test/core/preload.spec.js index edb3c2153b..aea0e11862 100644 --- a/test/core/preload.spec.js +++ b/test/core/preload.spec.js @@ -204,9 +204,9 @@ describe('preload', () => { expect(err).to.not.exist() ipfs.object.patch.addLink(result.parent.cid, { - name: 'link', - cid: result.link.cid, - size: result.link.node.size + Name: 'link', + Hash: result.link.cid, + Tsize: result.link.node.size }, (err, cid) => { expect(err).to.not.exist() MockPreloadNode.waitForCids(cid.toBaseEncodedString(), done) diff --git a/test/http-api/block.js b/test/http-api/block.js index afa8933833..1efce99d05 100644 --- a/test/http-api/block.js +++ b/test/http-api/block.js @@ -5,12 +5,12 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const multihash = require('multihashes') const waterfall = require('async/waterfall') const DaemonFactory = require('ipfsd-ctl') -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const df = DaemonFactory.create({ exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) }) describe('block endpoint', () => { let ipfs = null diff --git a/test/http-api/bootstrap.js b/test/http-api/bootstrap.js index 7fb59d6474..b53ba29fdf 100644 --- a/test/http-api/bootstrap.js +++ b/test/http-api/bootstrap.js @@ -6,9 +6,9 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const DaemonFactory = require('ipfsd-ctl') -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const df = DaemonFactory.create({ exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) }) describe('bootstrap endpoint', () => { let ipfs = null diff --git a/test/http-api/config.js b/test/http-api/config.js index 87c6b4d35d..51eb3e6e01 100644 --- a/test/http-api/config.js +++ b/test/http-api/config.js @@ -17,7 +17,7 @@ const fs = require('fs') const path = require('path') const DaemonFactory = require('ipfsd-ctl') -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const df = DaemonFactory.create({ exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) }) skipOnWindows('config endpoint', () => { const repoExample = path.join(__dirname, '../fixtures/go-ipfs-repo') diff --git a/test/http-api/dns.js b/test/http-api/dns.js index b90802a621..f27e5ee217 100644 --- a/test/http-api/dns.js +++ b/test/http-api/dns.js @@ -5,9 +5,9 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const DaemonFactory = require('ipfsd-ctl') -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const df = DaemonFactory.create({ exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) }) describe('dns endpoint', () => { let ipfs = null diff --git a/test/http-api/files.js b/test/http-api/files.js index 59bd05e118..66a508c34e 100644 --- a/test/http-api/files.js +++ b/test/http-api/files.js @@ -10,8 +10,8 @@ chai.use(dirtyChai) const { FILE_TYPES } = require('ipfs-mfs') - -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const path = require('path') +const df = DaemonFactory.create({ exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) }) describe('.files', () => { let ipfs = null diff --git a/test/http-api/id.js b/test/http-api/id.js index ea54e158ee..05052d83fe 100644 --- a/test/http-api/id.js +++ b/test/http-api/id.js @@ -15,7 +15,7 @@ const isWindows = require('../utils/platforms').isWindows const skipOnWindows = isWindows() ? describe.skip : describe const DaemonFactory = require('ipfsd-ctl') -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const df = DaemonFactory.create({ exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) }) skipOnWindows('id endpoint', () => { const repoExample = path.join(__dirname, '../fixtures/go-ipfs-repo') diff --git a/test/http-api/inject/dag.js b/test/http-api/inject/dag.js index 605cb076dd..fb4d2a823e 100644 --- a/test/http-api/inject/dag.js +++ b/test/http-api/inject/dag.js @@ -6,9 +6,7 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) -const promisify = require('promisify-es6') const DAGNode = require('ipld-dag-pb').DAGNode -const createDAGPBNode = promisify(DAGNode.create) const Readable = require('stream').Readable const FormData = require('form-data') const streamToPromise = require('stream-to-promise') @@ -58,7 +56,7 @@ module.exports = (http) => { }) it('returns value', async () => { - const node = await createDAGPBNode(Buffer.from([]), []) + const node = DAGNode.create(Buffer.from([]), []) const cid = await http.api._ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' @@ -75,7 +73,7 @@ module.exports = (http) => { }) it('uses text encoding for data by default', async () => { - const node = await createDAGPBNode(Buffer.from([0, 1, 2, 3]), []) + const node = DAGNode.create(Buffer.from([0, 1, 2, 3]), []) const cid = await http.api._ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' @@ -93,7 +91,7 @@ module.exports = (http) => { }) it('overrides data encoding', async () => { - const node = await createDAGPBNode(Buffer.from([0, 1, 2, 3]), []) + const node = DAGNode.create(Buffer.from([0, 1, 2, 3]), []) const cid = await http.api._ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' @@ -128,7 +126,7 @@ module.exports = (http) => { }) it('returns value with a path as part of the cid for dag-pb nodes', async () => { - const node = await createDAGPBNode(Buffer.from([0, 1, 2, 3]), []) + const node = DAGNode.create(Buffer.from([0, 1, 2, 3]), []) const cid = await http.api._ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' @@ -235,8 +233,8 @@ module.exports = (http) => { const added = await http.api._ipfs.dag.get(cid) - expect(added.value.data).to.be.empty() - expect(added.value.links).to.be.empty() + expect(added.value.Data).to.be.empty() + expect(added.value.Links).to.be.empty() }) it('adds a raw node', async () => { @@ -276,7 +274,7 @@ module.exports = (http) => { const cid = new CID(res.result.Cid['/']) const pinset = await http.api._ipfs.pin.ls() - expect(pinset.map(pin => pin.hash)).to.contain(cid.toBaseEncodedString('base58btc')) + expect(pinset.map(pin => pin.hash)).to.contain(cid.toBaseEncodedString()) }) it('does not pin a node after adding', async () => { @@ -387,9 +385,7 @@ module.exports = (http) => { }) const node1 = { - foo: { - '/': cid2 - } + foo: cid2 } const cid1 = await http.api._ipfs.dag.put(node1, { diff --git a/test/http-api/interface.js b/test/http-api/interface.js index eea370a4b7..43c6ff6a12 100644 --- a/test/http-api/interface.js +++ b/test/http-api/interface.js @@ -3,10 +3,11 @@ const tests = require('interface-ipfs-core') const CommonFactory = require('../utils/interface-common-factory') +const path = require('path') describe('interface-ipfs-core over ipfs-http-client tests', () => { const defaultCommonFactory = CommonFactory.create({ - factoryOptions: { exec: 'src/cli/bin.js' } + factoryOptions: { exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) } }) tests.bitswap(defaultCommonFactory) diff --git a/test/http-api/object.js b/test/http-api/object.js index 811aad6d72..eba7cdce6a 100644 --- a/test/http-api/object.js +++ b/test/http-api/object.js @@ -6,13 +6,16 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const fs = require('fs') const dagPB = require('ipld-dag-pb') const DAGLink = dagPB.DAGLink const DaemonFactory = require('ipfsd-ctl') -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const df = DaemonFactory.create({ + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), + IpfsClient: require('ipfs-http-client') +}) function asJson (cb) { return (err, result) => { diff --git a/test/http-api/version.js b/test/http-api/version.js index 9fc0c3acc0..3b92a30b6c 100644 --- a/test/http-api/version.js +++ b/test/http-api/version.js @@ -5,9 +5,9 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const DaemonFactory = require('ipfsd-ctl') -const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) +const df = DaemonFactory.create({ exec: path.resolve(`${__dirname}/../../src/cli/bin.js`) }) describe('version endpoint', () => { let ipfs = null diff --git a/test/utils/ipfs-exec.js b/test/utils/ipfs-exec.js index 3f9572f2a3..f4be357c02 100644 --- a/test/utils/ipfs-exec.js +++ b/test/utils/ipfs-exec.js @@ -5,7 +5,7 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) - +const path = require('path') const _ = require('lodash') // This is our new test utility to easily check and execute ipfs cli commands. @@ -27,9 +27,8 @@ module.exports = (repoPath, opts) => { env: env, timeout: 60 * 1000 }, opts) - - const exec = (args) => execa(`${process.cwd()}/src/cli/bin.js`, args, config) - const execRaw = (args) => execa(`${process.cwd()}/src/cli/bin.js`, args, Object.assign({}, config, { + const exec = (args) => execa(path.resolve(`${__dirname}/../../src/cli/bin.js`), args, config) + const execRaw = (args) => execa(path.resolve(`${__dirname}/../../src/cli/bin.js`), args, Object.assign({}, config, { encoding: null })) diff --git a/test/utils/on-and-off.js b/test/utils/on-and-off.js index d315491b90..840d7bbe8e 100644 --- a/test/utils/on-and-off.js +++ b/test/utils/on-and-off.js @@ -13,6 +13,7 @@ const os = require('os') const DaemonFactory = require('ipfsd-ctl') const df = DaemonFactory.create() +const path = require('path') function off (tests) { describe('daemon off (directly to core)', () => { @@ -51,7 +52,7 @@ function on (tests) { df.spawn({ type: 'js', - exec: `./src/cli/bin.js`, + exec: path.resolve(`${__dirname}/../../src/cli/bin.js`), initOptions: { bits: 512 }, config: { Bootstrap: [] } }, (err, node) => {