diff --git a/src/cli/commands/bitswap/unwant.js b/src/cli/commands/bitswap/unwant.js index 840276e9b2..ea676450fa 100644 --- a/src/cli/commands/bitswap/unwant.js +++ b/src/cli/commands/bitswap/unwant.js @@ -1,11 +1,25 @@ 'use strict' +const print = require('../../utils').print + module.exports = { command: 'unwant ', - describe: 'Remove a given block from your wantlist.', + describe: 'Removes a given block from your wantlist.', + builder: { + key: { + alias: 'k', + describe: 'Key to remove from your wantlist', + type: 'string' + } + }, handler (argv) { - throw new Error('Not implemented yet') + argv.ipfs.bitswap.unwant(argv.key, (err) => { + if (err) { + throw err + } + print(`Key ${argv.key} removed from wantlist`) + }) } } diff --git a/src/cli/commands/bitswap/wantlist.js b/src/cli/commands/bitswap/wantlist.js index 63692a993a..8ad26a439a 100644 --- a/src/cli/commands/bitswap/wantlist.js +++ b/src/cli/commands/bitswap/wantlist.js @@ -21,8 +21,8 @@ module.exports = { if (err) { throw err } - res.Keys.forEach((cidStr) => { - print(cidStr) + res.Keys.forEach((cid) => { + print(cid['/']) }) }) } diff --git a/src/cli/commands/block/get.js b/src/cli/commands/block/get.js index ed753aeadb..dd1e21d7fc 100644 --- a/src/cli/commands/block/get.js +++ b/src/cli/commands/block/get.js @@ -1,6 +1,7 @@ 'use strict' const CID = require('cids') +const print = require('../../utils').print module.exports = { command: 'get ', @@ -17,7 +18,11 @@ module.exports = { throw err } - process.stdout.write(block.data) + if (block) { + print(block.data) + } else { + print('Block was unwanted before it could be remotely retrieved') + } }) } } diff --git a/src/core/components/bitswap.js b/src/core/components/bitswap.js index e148f8c165..9f3c7bfbab 100644 --- a/src/core/components/bitswap.js +++ b/src/core/components/bitswap.js @@ -4,21 +4,23 @@ const OFFLINE_ERROR = require('../utils').OFFLINE_ERROR const promisify = require('promisify-es6') const setImmediate = require('async/setImmediate') const Big = require('big.js') +const CID = require('cids') function formatWantlist (list) { - return Array.from(list).map((e) => e[1]) + return Array.from(list).map((e) => ({ '/': e[1].cid.toBaseEncodedString() })) } module.exports = function bitswap (self) { return { - wantlist: () => { + wantlist: promisify((callback) => { if (!self.isOnline()) { - throw new Error(OFFLINE_ERROR) + return setImmediate(() => callback(new Error(OFFLINE_ERROR))) } - const list = self._bitswap.getWantlist() - return formatWantlist(list) - }, + let list = self._bitswap.getWantlist() + list = formatWantlist(list) + callback(null, { Keys: list }) + }), stat: promisify((callback) => { if (!self.isOnline()) { @@ -40,12 +42,21 @@ module.exports = function bitswap (self) { }) }), - unwant: (key) => { + unwant: promisify((keys, callback) => { if (!self.isOnline()) { - throw new Error(OFFLINE_ERROR) + return setImmediate(() => callback(new Error(OFFLINE_ERROR))) } - // TODO: implement when https://github.com/ipfs/js-ipfs-bitswap/pull/10 is merged - } + if (!Array.isArray(keys)) { + keys = [keys] + } + keys = keys.map((key) => { + if (CID.isCID(key)) { + return key + } + return new CID(key) + }) + callback(null, self._bitswap.unwant(keys)) + }) } } diff --git a/src/http/api/resources/bitswap.js b/src/http/api/resources/bitswap.js index da830c6415..f846d87ba2 100644 --- a/src/http/api/resources/bitswap.js +++ b/src/http/api/resources/bitswap.js @@ -7,16 +7,11 @@ const parseKey = require('./block').parseKey exports = module.exports exports.wantlist = (request, reply) => { - let list - try { - list = request.server.app.ipfs.bitswap.wantlist() - list = list.map((entry) => entry.cid.toBaseEncodedString()) - } catch (err) { - return reply(boom.badRequest(err)) - } - - reply({ - Keys: list + request.server.app.ipfs.bitswap.wantlist((err, list) => { + if (err) { + return reply(boom.badRequest(err)) + } + reply(list) }) } @@ -46,10 +41,18 @@ exports.stat = (request, reply) => { } exports.unwant = { - // uses common parseKey method that returns a `key` + // uses common parseKey method that assigns a `key` to request.pre.args parseArgs: parseKey, + // main route handler which is called after the above `parseArgs`, but only if the args were valid handler: (request, reply) => { - reply(boom.badRequest(new Error('Not implemented yet'))) + const key = request.pre.args.key + const ipfs = request.server.app.ipfs + ipfs.bitswap.unwant(key, (err) => { + if (err) { + return reply(boom.badRequest(err)) + } + reply({ key: key.toBaseEncodedString() }) + }) } } diff --git a/src/http/api/resources/block.js b/src/http/api/resources/block.js index 77553cbcaf..f536fb2a22 100644 --- a/src/http/api/resources/block.js +++ b/src/http/api/resources/block.js @@ -48,7 +48,13 @@ exports.get = { }).code(500) } - return reply(block.data) + if (block) { + return reply(block.data) + } + return reply({ + Message: 'Block was unwanted before it could be remotely retrieved', + Code: 0 + }).code(404) }) } } diff --git a/test/cli/bitswap.js b/test/cli/bitswap.js index 6652364f9b..6cdebe61de 100644 --- a/test/cli/bitswap.js +++ b/test/cli/bitswap.js @@ -13,7 +13,7 @@ describe('bitswap', () => runOn((thing) => { ipfs('block get ' + key) .then(() => {}) .catch(() => {}) - setTimeout(done, 800) + setTimeout(done, 250) }) it('wantlist', function () { @@ -23,8 +23,7 @@ describe('bitswap', () => runOn((thing) => { }) }) - // TODO @hacdias fix this with https://github.com/ipfs/js-ipfs/pull/1198 - it.skip('stat', function () { + it('stat', function () { this.timeout(20 * 1000) return ipfs('bitswap stat').then((out) => { @@ -40,4 +39,10 @@ describe('bitswap', () => runOn((thing) => { ].join('\n') + '\n') }) }) + + it('unwant', function () { + return ipfs('bitswap unwant ' + key).then((out) => { + expect(out).to.eql(`Key ${key} removed from wantlist\n`) + }) + }) })) diff --git a/test/core/bitswap.spec.js b/test/core/bitswap.spec.js index d9c9db978c..645581f2c1 100644 --- a/test/core/bitswap.spec.js +++ b/test/core/bitswap.spec.js @@ -18,9 +18,6 @@ const CID = require('cids') const IPFSFactory = require('ipfsd-ctl') -// This gets replaced by '../utils/create-repo-browser.js' in the browser -const createTempRepo = require('../utils/create-repo-nodejs.js') - const IPFS = require('../../src/core') // TODO bitswap tests on windows is failing, missing proper shutdown of daemon @@ -247,75 +244,4 @@ skipOnWindows('bitswap', function () { }) }) }) - - describe('api', () => { - let node - - before(function (done) { - this.timeout(40 * 1000) - - node = new IPFS({ - repo: createTempRepo(), - start: false, - config: { - Addresses: { - Swarm: [] - }, - Discovery: { - MDNS: { - Enabled: false - } - } - } - }) - node.on('ready', () => done()) - }) - - describe('while offline', () => { - it('.wantlist throws if offline', () => { - expect(() => node.bitswap.wantlist()).to.throw(/online/) - }) - - it('.stat gives error while offline', () => { - node.bitswap.stat((err, stats) => { - expect(err).to.exist() - expect(stats).to.not.exist() - }) - }) - - it('throws if offline', () => { - expect(() => node.bitswap.unwant('my key')).to.throw(/online/) - }) - }) - - describe('while online', () => { - before(function (done) { - this.timeout(80 * 1000) - - node.start(() => done()) - }) - - it('.wantlist returns an array of wanted blocks', () => { - expect(node.bitswap.wantlist()).to.eql([]) - }) - - it('returns the stats', (done) => { - node.bitswap.stat((err, stats) => { - expect(err).to.not.exist() - expect(stats).to.have.keys([ - 'blocksReceived', - 'blocksSent', - 'dataReceived', - 'dataSent', - 'wantlist', - 'peers', - 'provideBufLen', - 'dupDataReceived', - 'dupBlksReceived' - ]) - done() - }) - }) - }) - }) }) diff --git a/test/core/interface/bitswap.js b/test/core/interface/bitswap.js new file mode 100644 index 0000000000..b7927dd5dd --- /dev/null +++ b/test/core/interface/bitswap.js @@ -0,0 +1,35 @@ +/* eslint-env mocha */ +'use strict' + +const test = require('interface-ipfs-core') +const parallel = require('async/parallel') + +const IPFS = require('../../../src') + +const DaemonFactory = require('ipfsd-ctl') +const df = DaemonFactory.create({ type: 'proc', exec: IPFS }) + +const nodes = [] +const common = { + setup: function (callback) { + callback(null, { + spawnNode: (cb) => { + df.spawn({ + initOptions: { bits: 512 } + }, (err, _ipfsd) => { + if (err) { + return cb(err) + } + + nodes.push(_ipfsd) + cb(null, _ipfsd.api) + }) + } + }) + }, + teardown: function (callback) { + parallel(nodes.map((node) => (cb) => node.stop(cb)), callback) + } +} + +test.bitswap(common) diff --git a/test/http-api/index.js b/test/http-api/index.js index 44d48f7f1f..924b2b43d9 100644 --- a/test/http-api/index.js +++ b/test/http-api/index.js @@ -1,11 +1,12 @@ 'use strict' -require('./interface') -require('./inject') +require('./bitswap') require('./block') require('./bootstrap') require('./config') require('./dns') require('./id') +require('./inject') +require('./interface') require('./object') require('./version') diff --git a/test/http-api/interface/bitswap.js b/test/http-api/interface/bitswap.js new file mode 100644 index 0000000000..231a41cfe2 --- /dev/null +++ b/test/http-api/interface/bitswap.js @@ -0,0 +1,31 @@ +/* eslint-env mocha */ +'use strict' + +const test = require('interface-ipfs-core') +const parallel = require('async/parallel') + +const DaemonFactory = require('ipfsd-ctl') +const df = DaemonFactory.create({ exec: 'src/cli/bin.js' }) + +const nodes = [] +const common = { + setup: function (callback) { + callback(null, { + spawnNode: (cb) => { + df.spawn({ initOptions: { bits: 512 } }, (err, _ipfsd) => { + if (err) { + return cb(err) + } + + nodes.push(_ipfsd) + cb(null, _ipfsd.api) + }) + } + }) + }, + teardown: function (callback) { + parallel(nodes.map((node) => (cb) => node.stop(cb)), callback) + } +} + +test.bitswap(common)