diff --git a/src/cli/commands/files/add.js b/src/cli/commands/files/add.js index ebd4c7035b..61b849ff06 100644 --- a/src/cli/commands/files/add.js +++ b/src/cli/commands/files/add.js @@ -183,6 +183,18 @@ module.exports = { throw new Error('Implied argument raw-leaves must be passed and set to false when cid-version is > 0') } + // Temporary restriction on raw-leaves: + // When hash != undefined then raw-leaves MUST be present and false. + // + // This is because raw-leaves is not yet implemented in js-ipfs, + // and go-ipfs changes the value of raw-leaves to true when + // hash != undefined unless explicitly set to false. + // + // This retains feature parity without having to implement raw-leaves. + if (argv.hash && argv.rawLeaves !== false) { + throw new Error('Implied argument raw-leaves must be passed and set to false when hash argument is specified') + } + if (argv.rawLeaves) { throw new Error('Not implemented: raw-leaves') } diff --git a/src/core/components/files.js b/src/core/components/files.js index 8bd2f8e1b2..754bce6d76 100644 --- a/src/core/components/files.js +++ b/src/core/components/files.js @@ -20,8 +20,7 @@ module.exports = function files (self) { shardSplitThreshold: self._options.EXPERIMENTAL.sharding ? 1000 : Infinity }, options) - // CID v0 is for multihashes encoded with sha2-256 - if (opts.hashAlg && opts.hashAlg !== 'sha2-256' && opts.cidVersion !== 1) { + if (opts.hashAlg && opts.cidVersion !== 1) { opts.cidVersion = 1 } @@ -70,8 +69,10 @@ module.exports = function files (self) { return callback(new Error('Invalid arguments, data must be an object, Buffer or readable stream')) } + options = options || {} + // CID v0 is for multihashes encoded with sha2-256 - if (options && options.hashAlg && options.hashAlg !== 'sha2-256' && options.cidVersion !== 1) { + if (options.hashAlg && options.cidVersion !== 1) { options.cidVersion = 1 } @@ -127,15 +128,15 @@ module.exports = function files (self) { function prepareFile (self, opts, file, callback) { opts = opts || {} - waterfall([ - (cb) => self.object.get(file.multihash, cb), - (node, cb) => { - let cid = new CID(file.multihash) + let cid = new CID(file.multihash) - if (opts.cidVersion === 1) { - cid = cid.toV1() - } + if (opts.cidVersion === 1) { + cid = cid.toV1() + } + waterfall([ + (cb) => self.object.get(cid, cb), + (node, cb) => { const b58Hash = cid.toBaseEncodedString() cb(null, { diff --git a/src/core/components/object.js b/src/core/components/object.js index 4c716c4504..67ce5c6be8 100644 --- a/src/core/components/object.js +++ b/src/core/components/object.js @@ -10,20 +10,6 @@ const mh = require('multihashes') const Unixfs = require('ipfs-unixfs') const assert = require('assert') -function normalizeMultihash (multihash, enc) { - if (typeof multihash === 'string') { - if (enc === 'base58' || !enc) { - return multihash - } - - return new Buffer(multihash, enc) - } else if (Buffer.isBuffer(multihash)) { - return multihash - } else { - throw new Error('unsupported multihash') - } -} - function parseBuffer (buf, encoding, callback) { switch (encoding) { case 'json': @@ -178,20 +164,19 @@ module.exports = function object (self) { } }), - get: promisify((multihash, options, callback) => { + get: promisify((hash, options, callback) => { if (typeof options === 'function') { callback = options options = {} } - let mh + let cid try { - mh = normalizeMultihash(multihash, options.enc) + cid = new CID(hash) } catch (err) { return callback(err) } - const cid = new CID(mh) self._ipldResolver.get(cid, (err, result) => { if (err) { @@ -204,13 +189,21 @@ module.exports = function object (self) { }) }), - data: promisify((multihash, options, callback) => { + data: promisify((hash, options, callback) => { if (typeof options === 'function') { callback = options options = {} } - self.object.get(multihash, options, (err, node) => { + let cid + + try { + cid = new CID(hash) + } catch (err) { + return callback(err) + } + + self.object.get(cid, options, (err, node) => { if (err) { return callback(err) } diff --git a/src/http-api/resources/files.js b/src/http-api/resources/files.js index 43cd2f0950..5b4b7fd7c4 100644 --- a/src/http-api/resources/files.js +++ b/src/http-api/resources/files.js @@ -145,20 +145,19 @@ exports.add = { query: Joi.object() .keys({ 'cid-version': Joi.number().integer().min(0).max(1), + hash: Joi.string().valid(Object.keys(mh.names)), // Temporary restriction on raw-leaves: - // When cid-version=1 then raw-leaves MUST be present and false. + // When cid-version > 0 or hash != undefined then raw-leaves MUST be + // present and false. // // This is because raw-leaves is not yet implemented in js-ipfs, // and go-ipfs changes the value of raw-leaves to true when - // cid-version > 0 unless explicitly set to false. + // cid-version > 0 or hash != undefined unless explicitly set to false. // // This retains feature parity without having to implement raw-leaves. - 'raw-leaves': Joi.any().when('cid-version', { - is: 1, - then: Joi.boolean().valid(false).required(), - otherwise: Joi.boolean().valid(false) - }), - hash: Joi.string().valid(Object.keys(mh.names)) + 'raw-leaves': Joi.boolean().valid(false) + .when('cid-version', { is: 1, then: Joi.required() }) + .when('hash', { is: Joi.string(), then: Joi.required() }) }) // TODO: Necessary until validate "recursive", "stream-channels" etc. .options({ allowUnknown: true }) diff --git a/src/http-api/resources/object.js b/src/http-api/resources/object.js index 4a366f4e60..091312b682 100644 --- a/src/http-api/resources/object.js +++ b/src/http-api/resources/object.js @@ -7,6 +7,7 @@ const DAGLink = dagPB.DAGLink const DAGNode = dagPB.DAGNode const waterfall = require('async/waterfall') const series = require('async/series') +const CID = require('cids') const debug = require('debug') const log = debug('jsipfs:http-api:object') log.error = debug('jsipfs:http-api:object:error') @@ -20,9 +21,7 @@ exports.parseKey = (request, reply) => { } try { - return reply({ - key: mh.fromB58String(request.query.arg) - }) + return reply({ key: new CID(request.query.arg) }) } catch (err) { log.error(err) return reply({ diff --git a/test/cli/files.js b/test/cli/files.js index 9a9c4e3d66..599868dc0c 100644 --- a/test/cli/files.js +++ b/test/cli/files.js @@ -10,6 +10,18 @@ const CID = require('cids') const mh = require('multihashes') const runOnAndOff = require('../utils/on-and-off') +// TODO: Test against all algorithms Object.keys(mh.names) +// This subset is known to work with both go-ipfs and js-ipfs as of 2017-09-05 +const HASH_ALGS = [ + 'sha1', + 'sha2-256', + 'sha2-512', + 'keccak-224', + 'keccak-256', + 'keccak-384', + 'keccak-512' +] + describe('files', () => runOnAndOff((thing) => { let ipfs const readme = fs.readFileSync(path.join(process.cwd(), '/src/init-files/init-docs/readme')) @@ -224,9 +236,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - Object.keys(mh.names).forEach((name) => { - it('add with hash=' + name, () => { - return ipfs('add src/init-files/init-docs/readme --hash=' + name) + HASH_ALGS.forEach((name) => { + it(`add with hash=${name} and raw-leaves=false`, () => { + return ipfs(`add src/init-files/init-docs/readme --hash=${name} --raw-leaves=false`) .then((out) => { const hash = out.split(' ')[1] const cid = new CID(hash)