From 6b9fc9544c32123a725a277f8bb916d70f5ea9f7 Mon Sep 17 00:00:00 2001 From: David Dias Date: Wed, 14 Feb 2018 12:01:53 +0100 Subject: [PATCH 01/10] feat: use PubSub API directly from libp2p --- src/core/components/libp2p.js | 5 +-- src/core/components/no-floodsub.js | 24 ------------ src/core/components/pubsub.js | 62 ++++-------------------------- src/core/components/start.js | 12 +----- src/core/components/stop.js | 1 - test/core/bitswap.spec.js | 15 ++++---- 6 files changed, 18 insertions(+), 101 deletions(-) delete mode 100644 src/core/components/no-floodsub.js diff --git a/src/core/components/libp2p.js b/src/core/components/libp2p.js index e998517f01..8935fe3e4d 100644 --- a/src/core/components/libp2p.js +++ b/src/core/components/libp2p.js @@ -21,6 +21,7 @@ module.exports = function libp2p (self) { bootstrap: get(config, 'Bootstrap'), modules: self._libp2pModules, // EXPERIMENTAL + pubsub: get(self._options, 'EXPERIMENTAL.pubsub', false), dht: get(self._options, 'EXPERIMENTAL.dht', false), relay: { enabled: get(config, 'EXPERIMENTAL.relay.enabled', false), @@ -50,9 +51,7 @@ module.exports = function libp2p (self) { }) self._libp2pNode.start((err) => { - if (err) { - return callback(err) - } + if (err) { return callback(err) } self._libp2pNode.peerInfo.multiaddrs.forEach((ma) => { console.log('Swarm listening on', ma.toString()) diff --git a/src/core/components/no-floodsub.js b/src/core/components/no-floodsub.js deleted file mode 100644 index 95db571f5f..0000000000 --- a/src/core/components/no-floodsub.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' - -const EventEmitter = require('events') - -function fail () { - throw new Error('The daemon must be run with \'--enable-pubsub-experiment\'') -} - -class NoFloodSub extends EventEmitter { - constructor () { - super() - - this.peers = new Map() - this.subscriptions = new Set() - } - - start (callback) { callback() } - stop (callback) { callback() } - publish () { fail() } - subscribe () { fail() } - unsubscribe () { fail() } -} - -module.exports = NoFloodSub diff --git a/src/core/components/pubsub.js b/src/core/components/pubsub.js index 7e51062f40..8d1204876e 100644 --- a/src/core/components/pubsub.js +++ b/src/core/components/pubsub.js @@ -1,35 +1,19 @@ 'use strict' const promisify = require('promisify-es6') -const setImmediate = require('async/setImmediate') - -const OFFLINE_ERROR = require('../utils').OFFLINE_ERROR module.exports = function pubsub (self) { return { subscribe: (topic, options, handler, callback) => { - if (!self.isOnline()) { - throw new Error(OFFLINE_ERROR) - } - if (typeof options === 'function') { callback = handler handler = options options = {} } - function subscribe (cb) { - if (self._pubsub.listenerCount(topic) === 0) { - self._pubsub.subscribe(topic) - } - - self._pubsub.on(topic, handler) - setImmediate(cb) - } - if (!callback) { return new Promise((resolve, reject) => { - subscribe((err) => { + self.libp2p.pubsub.subscribe(topic, options, handler, (err) => { if (err) { return reject(err) } @@ -37,60 +21,28 @@ module.exports = function pubsub (self) { }) }) } else { - subscribe(callback) + self.libp2p.pubsub.subscribe(topic, options, handler, callback) } }, unsubscribe: (topic, handler) => { - self._pubsub.removeListener(topic, handler) - - if (self._pubsub.listenerCount(topic) === 0) { - self._pubsub.unsubscribe(topic) - } + self.libp2p.pubsub.unsubscribe(topic, handler) }, publish: promisify((topic, data, callback) => { - if (!self.isOnline()) { - return setImmediate(() => callback(new Error(OFFLINE_ERROR))) - } - - if (!Buffer.isBuffer(data)) { - return setImmediate(() => callback(new Error('data must be a Buffer'))) - } - - self._pubsub.publish(topic, data) - setImmediate(() => callback()) + self.libp2p.pubsub.publish(topic, data, callback) }), ls: promisify((callback) => { - if (!self.isOnline()) { - return setImmediate(() => callback(new Error(OFFLINE_ERROR))) - } - - const subscriptions = Array.from(self._pubsub.subscriptions) - - setImmediate(() => callback(null, subscriptions)) + self.libp2p.pubsub.ls(callback) }), peers: promisify((topic, callback) => { - if (!self.isOnline()) { - return setImmediate(() => callback(new Error(OFFLINE_ERROR))) - } - - if (typeof topic === 'function') { - callback = topic - topic = null - } - - const peers = Array.from(self._pubsub.peers.values()) - .filter((peer) => topic ? peer.topics.has(topic) : true) - .map((peer) => peer.info.id.toB58String()) - - setImmediate(() => callback(null, peers)) + self.libp2p.pubsub.peers(topic, callback) }), setMaxListeners (n) { - return self._pubsub.setMaxListeners(n) + self.libp2p.pubsub.setMaxListeners(n) } } } diff --git a/src/core/components/start.js b/src/core/components/start.js index 3004cca34d..f0517b1ed9 100644 --- a/src/core/components/start.js +++ b/src/core/components/start.js @@ -2,8 +2,6 @@ const series = require('async/series') const Bitswap = require('ipfs-bitswap') -const FloodSub = require('libp2p-floodsub') -const NoFloodSub = require('./no-floodsub') const setImmediate = require('async/setImmediate') const promisify = require('promisify-es6') @@ -38,9 +36,7 @@ module.exports = (self) => { (cb) => self.preStart(cb), (cb) => self.libp2p.start(cb) ], (err) => { - if (err) { - return done(err) - } + if (err) { return done(err) } self._bitswap = new Bitswap( self._libp2pNode, @@ -50,11 +46,7 @@ module.exports = (self) => { self._bitswap.start() self._blockService.setExchange(self._bitswap) - - self._pubsub = self._options.EXPERIMENTAL.pubsub - ? new FloodSub(self._libp2pNode) - : new NoFloodSub() - self._pubsub.start(done) + done() }) }) } diff --git a/src/core/components/stop.js b/src/core/components/stop.js index a39900d09c..4d35190d21 100644 --- a/src/core/components/stop.js +++ b/src/core/components/stop.js @@ -32,7 +32,6 @@ module.exports = (self) => { self._bitswap.stop() series([ - (cb) => self._pubsub.stop(cb), (cb) => self.libp2p.stop(cb), (cb) => self._repo.close(cb) ], done) diff --git a/test/core/bitswap.spec.js b/test/core/bitswap.spec.js index b0260ed5ff..a186aaf352 100644 --- a/test/core/bitswap.spec.js +++ b/test/core/bitswap.spec.js @@ -16,10 +16,9 @@ const isNode = require('detect-node') const multihashing = require('multihashing-async') const CID = require('cids') -const DaemonFactory = require('ipfsd-ctl') -const df = DaemonFactory.create({ type: 'js' }) - -const dfProc = DaemonFactory.create({ type: 'proc' }) +const IPFSFactory = require('ipfsd-ctl') +const fDaemon = IPFSFactory.create({ type: 'js' }) +const fInProc = IPFSFactory.create({ type: 'proc' }) // This gets replaced by '../utils/create-repo-browser.js' in the browser const createTempRepo = require('../utils/create-repo-nodejs.js') @@ -69,7 +68,7 @@ function connectNodes (remoteNode, inProcNode, callback) { let nodes = [] function addNode (inProcNode, callback) { - df.spawn({ + fDaemon.spawn({ exec: './src/cli/bin.js', config: { Addresses: { @@ -89,7 +88,7 @@ function addNode (inProcNode, callback) { }) } -describe('bitswap', function () { +describe.only('bitswap', function () { this.timeout(80 * 1000) let inProcNode // Node spawned inside this process @@ -119,7 +118,7 @@ describe('bitswap', function () { }) } - dfProc.spawn({ exec: IPFS, config }, (err, _ipfsd) => { + fInProc.spawn({ exec: IPFS, config: config }, (err, _ipfsd) => { expect(err).to.not.exist() nodes.push(_ipfsd) inProcNode = _ipfsd.api @@ -137,7 +136,7 @@ describe('bitswap', function () { }) }) - describe('transfer a block between', () => { + describe.only('transfer a block between', () => { it('2 peers', function (done) { this.timeout(80 * 1000) From 6fe015fe89c86a8be10025ed793a8067db5e2f2d Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 15 Feb 2018 19:28:32 +0100 Subject: [PATCH 02/10] feat: all pubsub tests passing with libp2p pubsub --- src/core/components/pubsub.js | 14 +++++++------- test/core/bitswap.spec.js | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/components/pubsub.js b/src/core/components/pubsub.js index 8d1204876e..d5825960e2 100644 --- a/src/core/components/pubsub.js +++ b/src/core/components/pubsub.js @@ -13,7 +13,7 @@ module.exports = function pubsub (self) { if (!callback) { return new Promise((resolve, reject) => { - self.libp2p.pubsub.subscribe(topic, options, handler, (err) => { + self._libp2pNode.pubsub.subscribe(topic, options, handler, (err) => { if (err) { return reject(err) } @@ -21,28 +21,28 @@ module.exports = function pubsub (self) { }) }) } else { - self.libp2p.pubsub.subscribe(topic, options, handler, callback) + self._libp2pNode.pubsub.subscribe(topic, options, handler, callback) } }, unsubscribe: (topic, handler) => { - self.libp2p.pubsub.unsubscribe(topic, handler) + self._libp2pNode.pubsub.unsubscribe(topic, handler) }, publish: promisify((topic, data, callback) => { - self.libp2p.pubsub.publish(topic, data, callback) + self._libp2pNode.pubsub.publish(topic, data, callback) }), ls: promisify((callback) => { - self.libp2p.pubsub.ls(callback) + self._libp2pNode.pubsub.ls(callback) }), peers: promisify((topic, callback) => { - self.libp2p.pubsub.peers(topic, callback) + self._libp2pNode.pubsub.peers(topic, callback) }), setMaxListeners (n) { - self.libp2p.pubsub.setMaxListeners(n) + self._libp2pNode.pubsub.setMaxListeners(n) } } } diff --git a/test/core/bitswap.spec.js b/test/core/bitswap.spec.js index a186aaf352..b05244f249 100644 --- a/test/core/bitswap.spec.js +++ b/test/core/bitswap.spec.js @@ -88,7 +88,7 @@ function addNode (inProcNode, callback) { }) } -describe.only('bitswap', function () { +describe('bitswap', function () { this.timeout(80 * 1000) let inProcNode // Node spawned inside this process @@ -136,7 +136,7 @@ describe.only('bitswap', function () { }) }) - describe.only('transfer a block between', () => { + describe('transfer a block between', () => { it('2 peers', function (done) { this.timeout(80 * 1000) From f12226b9f8163e95b37085e2524f53053aed96f8 Mon Sep 17 00:00:00 2001 From: David Dias Date: Fri, 16 Feb 2018 18:39:12 +0000 Subject: [PATCH 03/10] chore: update libp2p --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d927d3913d..382d8f7326 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "is-ipfs": "^0.3.2", "is-stream": "^1.1.0", "joi": "^13.1.2", - "libp2p": "~0.16.5", + "libp2p": "~0.17.0", "libp2p-circuit": "~0.1.4", "libp2p-floodsub": "~0.14.1", "libp2p-kad-dht": "~0.8.0", From f7fb33ed8e8edb1a6d01f9a39fabf29e2df10788 Mon Sep 17 00:00:00 2001 From: David Dias Date: Sat, 17 Feb 2018 22:21:05 +0000 Subject: [PATCH 04/10] refactor: fix linting from bootstrap.js --- src/core/components/bootstrap.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/core/components/bootstrap.js b/src/core/components/bootstrap.js index 9ca1a76479..b5a497eac3 100644 --- a/src/core/components/bootstrap.js +++ b/src/core/components/bootstrap.js @@ -20,10 +20,10 @@ module.exports = function bootstrap (self) { args = {default: false} } try { - if (multiaddr) - new MultiAddr(multiaddr) - } - catch (err) { + if (multiaddr) { + multiaddr = new MultiAddr(multiaddr) + } + } catch (err) { return setImmediate(() => callback(err)) } self._repo.config.get((err, config) => { @@ -52,12 +52,13 @@ module.exports = function bootstrap (self) { args = {all: false} } try { - if (multiaddr) - new MultiAddr(multiaddr) - } - catch (err) { + if (multiaddr) { + multiaddr = new MultiAddr(multiaddr) + } + } catch (err) { return setImmediate(() => callback(err)) } + self._repo.config.get((err, config) => { if (err) { return callback(err) From afaaf2ba2d35e364355b58e98a13b70e527b0f2c Mon Sep 17 00:00:00 2001 From: David Dias Date: Sat, 17 Feb 2018 22:23:38 +0000 Subject: [PATCH 05/10] chore: update CI configs --- .travis.yml | 4 ---- circle.yml | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8253ebb93d..30e306640b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,15 +3,11 @@ language: node_js matrix: include: - - node_js: 6 - env: CXX=g++-4.8 - node_js: 8 env: CXX=g++-4.8 script: - - npm run lint - npm run test - - make test before_script: - export DISPLAY=:99.0 diff --git a/circle.yml b/circle.yml index e0338e62d4..445e40b5e0 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,10 @@ machine: version: stable test: + pre: + - npm run lint post: + - make test - npm run coverage -- --upload --providers coveralls dependencies: From d527b453b4f760c222922f3f00b29b4efb1dbbed Mon Sep 17 00:00:00 2001 From: David Dias Date: Sat, 17 Feb 2018 22:25:18 +0000 Subject: [PATCH 06/10] fix: bootstrap --- src/core/components/bootstrap.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core/components/bootstrap.js b/src/core/components/bootstrap.js index b5a497eac3..a57858abb3 100644 --- a/src/core/components/bootstrap.js +++ b/src/core/components/bootstrap.js @@ -1,7 +1,7 @@ 'use strict' const defaultNodes = require('../runtime/config-nodejs.json').Bootstrap -const MultiAddr = require('multiaddr') +// const MultiAddr = require('multiaddr') const promisify = require('promisify-es6') module.exports = function bootstrap (self) { @@ -21,7 +21,9 @@ module.exports = function bootstrap (self) { } try { if (multiaddr) { - multiaddr = new MultiAddr(multiaddr) + // TODO understand what was the purpose of this code + // it failed on tests, it passes without + // multiaddr = new MultiAddr(multiaddr) } } catch (err) { return setImmediate(() => callback(err)) @@ -53,7 +55,8 @@ module.exports = function bootstrap (self) { } try { if (multiaddr) { - multiaddr = new MultiAddr(multiaddr) + // TODO understand what was the purpose of this code + // multiaddr = new MultiAddr(multiaddr) } } catch (err) { return setImmediate(() => callback(err)) From 9f39a6f3b7b3c228dd6f3653a00cdb958d319385 Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 18 Feb 2018 07:59:52 +0000 Subject: [PATCH 07/10] fix: now properly fix bootstrap in core --- src/core/components/bootstrap.js | 40 ++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/core/components/bootstrap.js b/src/core/components/bootstrap.js index a57858abb3..559f8e05b3 100644 --- a/src/core/components/bootstrap.js +++ b/src/core/components/bootstrap.js @@ -1,9 +1,24 @@ 'use strict' const defaultNodes = require('../runtime/config-nodejs.json').Bootstrap -// const MultiAddr = require('multiaddr') +const Multiaddr = require('multiaddr') const promisify = require('promisify-es6') +function isValid (ma) { + if (typeof ma === 'string') { + try { + ma = new Multiaddr(ma) + return Boolean(ma) + } catch (err) { + return false + } + } else if (ma) { + return Multiaddr.isMultiaddr(ma) + } else { + return false + } +} + module.exports = function bootstrap (self) { return { list: promisify((callback) => { @@ -17,17 +32,13 @@ module.exports = function bootstrap (self) { add: promisify((multiaddr, args, callback) => { if (typeof args === 'function') { callback = args - args = {default: false} + args = { default: false } } - try { - if (multiaddr) { - // TODO understand what was the purpose of this code - // it failed on tests, it passes without - // multiaddr = new MultiAddr(multiaddr) - } - } catch (err) { - return setImmediate(() => callback(err)) + + if (multiaddr && !isValid(multiaddr)) { + return setImmediate(() => callback(new Error('Not valid multiaddr'))) } + self._repo.config.get((err, config) => { if (err) { return callback(err) @@ -53,13 +64,8 @@ module.exports = function bootstrap (self) { callback = args args = {all: false} } - try { - if (multiaddr) { - // TODO understand what was the purpose of this code - // multiaddr = new MultiAddr(multiaddr) - } - } catch (err) { - return setImmediate(() => callback(err)) + if (multiaddr && !isValid(multiaddr)) { + return setImmediate(() => callback(new Error('Not valid multiaddr'))) } self._repo.config.get((err, config) => { From 494da7f8c5b35f491f22a986ff5e8c456cc0e602 Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 18 Feb 2018 10:15:10 +0100 Subject: [PATCH 08/10] feat: `ipfs version` flags + `ipfs repo version` (#1181) (#1188) --- src/cli/commands/version.js | 35 +++++++++++++++--- src/core/components/repo.js | 20 +++++++++- src/core/components/version.js | 15 ++++++-- test/cli/files.js | 2 +- test/cli/repo.js | 21 +++++++++++ test/cli/version.js | 53 +++++++++++++++++++++++++-- test/sharness/t0010-basic-commands.sh | 5 ++- 7 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 test/cli/repo.js diff --git a/src/cli/commands/version.js b/src/cli/commands/version.js index 6d9ecb45d4..6bb8447a2f 100644 --- a/src/cli/commands/version.js +++ b/src/cli/commands/version.js @@ -1,5 +1,6 @@ 'use strict' +const os = require('os') const print = require('../utils').print module.exports = { @@ -11,26 +12,48 @@ module.exports = { number: { alias: 'n', type: 'boolean', - default: false + default: false, + describe: 'Print only the version number' }, commit: { type: 'boolean', - default: false + default: false, + describe: `Include the version's commit hash` }, repo: { type: 'boolean', - default: false + default: false, + describe: `Print only the repo's version number` + }, + all: { + type: 'boolean', + default: false, + describe: 'Print everything we have' } }, handler (argv) { - // TODO: handle argv.{repo|commit|number} - argv.ipfs.version((err, version) => { + argv.ipfs.version((err, data) => { if (err) { throw err } - print(`js-ipfs version: ${version.version}`) + const withCommit = argv.all || argv.commit + const parsedVersion = `${data.version}${withCommit ? `-${data.commit}` : ''}` + + if (argv.repo) { + // go-ipfs prints only the number, even without the --number flag. + print(data.repo) + } else if (argv.number) { + print(parsedVersion) + } else if (argv.all) { + print(`js-ipfs version: ${parsedVersion}`) + print(`Repo version: ${data.repo}`) + print(`System version: ${os.arch()}/${os.platform()}`) + print(`Node.js version: ${process.version}`) + } else { + print(`js-ipfs version: ${parsedVersion}`) + } }) } } diff --git a/src/core/components/repo.js b/src/core/components/repo.js index 989e07fd9e..dc330aba0e 100644 --- a/src/core/components/repo.js +++ b/src/core/components/repo.js @@ -1,6 +1,7 @@ 'use strict' const promisify = require('promisify-es6') +const repoVersion = require('ipfs-repo').repoVersion module.exports = function repo (self) { return { @@ -8,8 +9,25 @@ module.exports = function repo (self) { // 1. check if repo already exists }, + /** + * If the repo has been initialized, report the current version. + * Otherwise report the version that would be initialized. + * + * @param {function(Error, Number)} [callback] + * @returns {undefined} + */ version: promisify((callback) => { - self._repo.version.get(callback) + self._repo._isInitialized(err => { + if (err) { + if (/ENOENT|not yet initialized/.test(err.message)) { + // this repo has not been initialized + return callback(null, repoVersion) + } + return callback(err) + } + + self._repo.version.get(callback) + }) }), gc: () => {}, diff --git a/src/core/components/version.js b/src/core/components/version.js index 1d1fcca9c5..1afbc7a7fb 100644 --- a/src/core/components/version.js +++ b/src/core/components/version.js @@ -3,6 +3,7 @@ const pkg = require('../../../package.json') const promisify = require('promisify-es6') +// TODO add the commit hash of the current ipfs version to the response. module.exports = function version (self) { return promisify((opts, callback) => { if (typeof opts === 'function') { @@ -10,10 +11,16 @@ module.exports = function version (self) { opts = {} } - callback(null, { - version: pkg.version, - repo: '', - commit: '' + self.repo.version((err, repoVersion) => { + if (err) { + callback(err) + } + + callback(null, { + version: pkg.version, + repo: repoVersion, + commit: '' + }) }) }) } diff --git a/test/cli/files.js b/test/cli/files.js index 738b07e317..9fa95a0401 100644 --- a/test/cli/files.js +++ b/test/cli/files.js @@ -1,8 +1,8 @@ /* eslint-env mocha */ 'use strict' -const expect = require('chai').expect const fs = require('fs') +const expect = require('chai').expect const path = require('path') const compareDir = require('dir-compare').compareSync const rimraf = require('rimraf').sync diff --git a/test/cli/repo.js b/test/cli/repo.js new file mode 100644 index 0000000000..17c04aaaa3 --- /dev/null +++ b/test/cli/repo.js @@ -0,0 +1,21 @@ +/* eslint-env mocha */ +'use strict' + +const expect = require('chai').expect +const repoVersion = require('ipfs-repo').repoVersion + +const runOnAndOff = require('../utils/on-and-off') + +describe('repo', () => runOnAndOff((thing) => { + let ipfs + + before(() => { + ipfs = thing.ipfs + }) + + it('get the repo version', () => { + return ipfs('repo version').then((out) => { + expect(out).to.eql(`${repoVersion}\n`) + }) + }) +})) diff --git a/test/cli/version.js b/test/cli/version.js index 44986adf77..5bf740eb15 100644 --- a/test/cli/version.js +++ b/test/cli/version.js @@ -1,7 +1,10 @@ +/* eslint max-nested-callbacks: ["error", 5] */ /* eslint-env mocha */ 'use strict' +const os = require('os') const expect = require('chai').expect +const repoVersion = require('ipfs-repo').repoVersion const pkgversion = require('../../package.json').version const runOnAndOff = require('../utils/on-and-off') @@ -12,11 +15,55 @@ describe('version', () => runOnAndOff((thing) => { ipfs = thing.ipfs }) - it('get the version', () => { - return ipfs('version').then((out) => { + it('get the version', () => + ipfs('version').then(out => expect(out).to.eql( `js-ipfs version: ${pkgversion}\n` ) - }) + ) + ) + + it('handles --number', () => + ipfs('version --number').then(out => + expect(out).to.eql(`${pkgversion}\n`) + ) + ) + + it('handles --commit', () => + ipfs('version --commit').then(out => + expect(out).to.eql(`js-ipfs version: ${pkgversion}-\n`) + ) + ) + + describe('handles --all', function () { + it('prints js-ipfs version', () => + ipfs('version --all').then(out => { + expect(out).to.include(`js-ipfs version: ${pkgversion}`) + }) + ) + + it('prints repo version', () => + ipfs('version --all').then(out => { + expect(out).to.include(`Repo version: ${repoVersion}`) + }) + ) + + it('prints arch/platform', () => + ipfs('version --all').then(out => { + expect(out).to.include(`System version: ${os.arch()}/${os.platform()}`) + }) + ) + + it('prints Node.js version', () => + ipfs('version --all').then(out => { + expect(out).to.include(`Node.js version: ${process.version}`) + }) + ) }) + + it('handles --repo', () => + ipfs('version --repo').then(out => + expect(out).to.eql(`${repoVersion}\n`) + ) + ) })) diff --git a/test/sharness/t0010-basic-commands.sh b/test/sharness/t0010-basic-commands.sh index 402485051b..92f4354fdd 100755 --- a/test/sharness/t0010-basic-commands.sh +++ b/test/sharness/t0010-basic-commands.sh @@ -28,7 +28,10 @@ test_expect_success "ipfs version output looks good" ' test_expect_success "ipfs version --all has all required fields" ' ipfs version --all > version_all.txt && - grep "js-ipfs version" version_all.txt + grep "js-ipfs version" version_all.txt && + grep "Repo version" version_all.txt && + grep "System version" version_all.txt && + grep "Node.js version" version_all.txt ' test_expect_success "ipfs help succeeds" ' From d9744a165c4478626affc838a7890e9a5ebced7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=A0=C9=AA=E1=B4=84=E1=B4=9B=E1=B4=8F=CA=80=20=CA=99?= =?UTF-8?q?=E1=B4=8A=E1=B4=87=CA=9F=E1=B4=8B=CA=9C=E1=B4=8F=CA=9F=E1=B4=8D?= Date: Sun, 18 Feb 2018 21:08:18 +0100 Subject: [PATCH 09/10] feat: improved multiaddr validation. --- src/core/components/bootstrap.js | 29 +++++++++++++---------------- test/core/bootstrap.spec.js | 9 +++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/core/components/bootstrap.js b/src/core/components/bootstrap.js index 559f8e05b3..3d816ac946 100644 --- a/src/core/components/bootstrap.js +++ b/src/core/components/bootstrap.js @@ -1,24 +1,21 @@ 'use strict' const defaultNodes = require('../runtime/config-nodejs.json').Bootstrap -const Multiaddr = require('multiaddr') +const isMultiaddr = require('mafmt').IPFS.matches const promisify = require('promisify-es6') -function isValid (ma) { - if (typeof ma === 'string') { - try { - ma = new Multiaddr(ma) - return Boolean(ma) - } catch (err) { - return false - } - } else if (ma) { - return Multiaddr.isMultiaddr(ma) - } else { +function isValidMultiaddr (ma) { + try { + return isMultiaddr(ma) + } catch (err) { return false } } +function invalidMultiaddrError (ma) { + return new Error(`${ma} is not a valid Multiaddr`) +} + module.exports = function bootstrap (self) { return { list: promisify((callback) => { @@ -35,8 +32,8 @@ module.exports = function bootstrap (self) { args = { default: false } } - if (multiaddr && !isValid(multiaddr)) { - return setImmediate(() => callback(new Error('Not valid multiaddr'))) + if (multiaddr && !isValidMultiaddr(multiaddr)) { + return setImmediate(() => callback(invalidMultiaddrError(multiaddr))) } self._repo.config.get((err, config) => { @@ -64,8 +61,8 @@ module.exports = function bootstrap (self) { callback = args args = {all: false} } - if (multiaddr && !isValid(multiaddr)) { - return setImmediate(() => callback(new Error('Not valid multiaddr'))) + if (multiaddr && !isValidMultiaddr(multiaddr)) { + return setImmediate(() => callback(invalidMultiaddrError(multiaddr))) } self._repo.config.get((err, config) => { diff --git a/test/core/bootstrap.spec.js b/test/core/bootstrap.spec.js index 698af528b4..dd780ce8fd 100644 --- a/test/core/bootstrap.spec.js +++ b/test/core/bootstrap.spec.js @@ -115,4 +115,13 @@ describe('bootstrap', () => { }) }) }) + + it('fails if passing in a invalid multiaddr', (done) => { + node.bootstrap.add('/funky/invalid/multiaddr', (err, res) => { + expect(err).to.match(/not a valid Multiaddr/) + expect(err).to.match(/funky/) + expect(res).to.not.exist() + done() + }) + }) }) From e4d2a15143431a9af37a275a149621738c91aa00 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 16 Feb 2018 18:08:05 +0000 Subject: [PATCH 10/10] docs: Add browser example for streaming files --- examples/README.md | 1 + .../browser-add-readable-stream/README.md | 7 ++ .../browser-add-readable-stream/index.html | 7 ++ examples/browser-add-readable-stream/index.js | 75 +++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 examples/browser-add-readable-stream/README.md create mode 100644 examples/browser-add-readable-stream/index.html create mode 100644 examples/browser-add-readable-stream/index.js diff --git a/examples/README.md b/examples/README.md index 4b6f82ddc1..f8e591eb4e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -20,6 +20,7 @@ Let us know if you find any issue or if you want to contribute and add a new tut - [js-ipfs in the browser with WebPack](./browser-webpack) - [js-ipfs in the browser with a ` + + + diff --git a/examples/browser-add-readable-stream/index.js b/examples/browser-add-readable-stream/index.js new file mode 100644 index 0000000000..7ae4f87392 --- /dev/null +++ b/examples/browser-add-readable-stream/index.js @@ -0,0 +1,75 @@ +'use strict' + +/* global Ipfs */ +/* eslint-env browser */ + +const repoPath = 'ipfs-' + Math.random() +const ipfs = new Ipfs({ repo: repoPath }) + +ipfs.on('ready', () => { + const directory = 'directory' + + // Our list of files + const files = createFiles(directory) + + streamFiles(directory, files, (err, directoryHash) => { + if (err) { + return log(`There was an error adding the files ${err}`) + } + + ipfs.ls(directoryHash, (err, files) => { + if (err) { + return log(`There was an error listing the files ${err}`) + } + + log(` +-- + +Directory contents: + +${directory}/ ${directoryHash}`) + + files.forEach((file, index) => { + log(` ${index < files.length - 1 ? '\u251C' : '\u2514'}\u2500 ${file.name} ${file.path} ${file.hash}`) + }) + }) + }) +}) + +const createFiles = (directory) => { + return [{ + path: `${directory}/file1.txt`, + + // content could be a stream, a url etc + content: ipfs.types.Buffer.from('one', 'utf8') + }, { + path: `${directory}/file2.txt`, + content: ipfs.types.Buffer.from('two', 'utf8') + }, { + path: `${directory}/file3.txt`, + content: ipfs.types.Buffer.from('three', 'utf8') + }] +} + +const streamFiles = (directory, files, cb) => { + // Create a stream to write files to + const stream = ipfs.files.addReadableStream() + stream.on('data', function (data) { + log(`Added ${data.path} hash: ${data.hash}`) + + // The last data event will contain the directory hash + if (data.path === directory) { + cb(null, data.hash) + } + }) + + // Add the files one by one + files.forEach(file => stream.write(file)) + + // When we have no more files to add, close the stream + stream.end() +} + +const log = (line) => { + document.getElementById('output').appendChild(document.createTextNode(`${line}\r\n`)) +}