From 0a12b3e239b0b0a77f2c50d17ca46e5d47007ff2 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 16 Nov 2018 11:08:01 +0000 Subject: [PATCH] feat: allow write and mkdir with different hash algs and cid versions License: MIT Signed-off-by: achingbrain --- package.json | 1 + src/cli/mkdir.js | 6 +- src/core/mkdir.js | 6 +- src/core/write.js | 2 +- test/helpers/cid-at-path.js | 18 ++++++ test/helpers/index.js | 1 + test/mkdir.spec.js | 39 +++++++++++- test/write.spec.js | 122 +++++++++++++++++++++++++++++++----- 8 files changed, 171 insertions(+), 24 deletions(-) create mode 100644 test/helpers/cid-at-path.js diff --git a/package.json b/package.json index 6c58d50..9992b3b 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "detect-webworker": "^1.0.0", "dirty-chai": "^2.0.1", "ipld": "~0.20.0", + "multihashes": "~0.4.14", "pull-buffer-stream": "^1.0.0", "pull-traverse": "^1.0.3" }, diff --git a/src/cli/mkdir.js b/src/cli/mkdir.js index 545cb1d..c94dc1c 100644 --- a/src/cli/mkdir.js +++ b/src/cli/mkdir.js @@ -23,7 +23,7 @@ module.exports = { default: 0, describe: 'Cid version to use. (experimental).' }, - hash: { + hashAlg: { type: 'string', describe: 'Hash function to use. Will set Cid version to 1 if used. (experimental).' }, @@ -42,7 +42,7 @@ module.exports = { ipfs, parents, cidVersion, - hash, + hashAlg, flush } = argv @@ -50,7 +50,7 @@ module.exports = { ipfs.files.mkdir(path, { parents, cidVersion, - hash, + hashAlg, flush }) ) diff --git a/src/core/mkdir.js b/src/core/mkdir.js index 0f991c8..4b2c11c 100644 --- a/src/core/mkdir.js +++ b/src/core/mkdir.js @@ -11,7 +11,7 @@ const { const defaultOptions = { parents: false, - hash: undefined, + hashAlg: undefined, cidVersion: 0 } @@ -61,7 +61,9 @@ module.exports = (context) => { (cb) => traverseTo(context, path, { parents: options.parents, flush: options.flush, - createLastComponent: true + createLastComponent: true, + cidVersion: options.cidVersion, + hashAlg: options.hashAlg }, cb), (result, cb) => updateTree(context, result, cb), (newRoot, next) => updateMfsRoot(context, newRoot.cid, next) diff --git a/src/core/write.js b/src/core/write.js index 089fec0..1f8748a 100644 --- a/src/core/write.js +++ b/src/core/write.js @@ -272,7 +272,7 @@ const write = (context, existingNodeCid, existingNode, source, options, callback }]), importer(context.ipld, { progress: options.progress, - hashAlg: options.hash, + hashAlg: options.hashAlg, cidVersion: options.cidVersion, strategy: options.strategy, rawLeaves: options.rawLeaves, diff --git a/test/helpers/cid-at-path.js b/test/helpers/cid-at-path.js new file mode 100644 index 0000000..caf7644 --- /dev/null +++ b/test/helpers/cid-at-path.js @@ -0,0 +1,18 @@ +'use strict' + +const CID = require('cids') + +module.exports = async (path, mfs) => { + const parts = path.split('/') + const fileName = parts.pop() + const directory = `/${parts.join('/')}` + + return new CID( + (await mfs.ls(directory, { + long: true + })) + .filter(file => file.name === fileName) + .pop() + .hash + ) +} diff --git a/test/helpers/index.js b/test/helpers/index.js index 94a1d68..53c2f7f 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -31,6 +31,7 @@ const createMfs = async () => { module.exports = { createMfs, + cidAtPath: require('./cid-at-path'), collectLeafCids: require('./collect-leaf-cids'), EMPTY_DIRECTORY_HASH: 'QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn', EMPTY_DIRECTORY_HASH_BASE32: 'bafybeiczsscdsbs7ffqz55asqdf3smv6klcw3gofszvwlyarci47bgf354' diff --git a/test/mkdir.spec.js b/test/mkdir.spec.js index bbd6eae..35b07e7 100644 --- a/test/mkdir.spec.js +++ b/test/mkdir.spec.js @@ -4,8 +4,10 @@ const chai = require('chai') chai.use(require('dirty-chai')) const expect = chai.expect +const multihash = require('multihashes') const { - createMfs + createMfs, + cidAtPath } = require('./helpers') describe('mkdir', function () { @@ -105,11 +107,42 @@ describe('mkdir', function () { }) }) - it.skip('creates a nested directory with a different CID version to the parent', () => { + it('creates a nested directory with a different CID version to the parent', async () => { + const directory = `cid-versions-${Math.random()}` + const directoryPath = `/${directory}` + const subDirectory = `cid-versions-${Math.random()}` + const subDirectoryPath = `${directoryPath}/${subDirectory}` + await mfs.mkdir(directoryPath, { + cidVersion: 0 + }) + + expect((await cidAtPath(directoryPath, mfs)).version).to.equal(0) + + await mfs.mkdir(subDirectoryPath, { + cidVersion: 1 + }) + + expect((await cidAtPath(subDirectoryPath, mfs)).version).to.equal(1) }) - it.skip('creates a nested directory with a different hash function to the parent', () => { + it('creates a nested directory with a different hash function to the parent', async () => { + const directory = `cid-versions-${Math.random()}` + const directoryPath = `/${directory}` + const subDirectory = `cid-versions-${Math.random()}` + const subDirectoryPath = `${directoryPath}/${subDirectory}` + + await mfs.mkdir(directoryPath, { + cidVersion: 0 + }) + + expect((await cidAtPath(directoryPath, mfs)).version).to.equal(0) + + await mfs.mkdir(subDirectoryPath, { + cidVersion: 1, + hashAlg: 'sha2-512' + }) + expect(multihash.decode((await cidAtPath(subDirectoryPath, mfs)).multihash).name).to.equal('sha2-512') }) }) diff --git a/test/write.spec.js b/test/write.spec.js index 127939a..5087a28 100644 --- a/test/write.spec.js +++ b/test/write.spec.js @@ -9,9 +9,11 @@ const loadFixture = require('aegir/fixtures') const isNode = require('detect-node') const values = require('pull-stream/sources/values') const bufferStream = require('pull-buffer-stream') +const multihash = require('multihashes') const { collectLeafCids, - createMfs + createMfs, + cidAtPath } = require('./helpers') let fs @@ -489,26 +491,116 @@ describe('write', function () { }) }) - // https://github.com/ipld/js-ipld/issues/157 - it.skip('writes a file with a different CID version to the parent', () => { - const directory = '/cid-versions' - const fileName = `${directory}/file.txt` + it('writes a file with a different CID version to the parent', async () => { + const directory = `cid-versions-${Math.random()}` + const directoryPath = `/${directory}` + const fileName = `file-${Math.random()}.txt` + const filePath = `${directoryPath}/${fileName}` const expectedBytes = Buffer.from([0, 1, 2, 3]) - return mfs.mkdir(directory, { + await mfs.mkdir(directoryPath, { cidVersion: 0 }) - .then(() => mfs.write(fileName, expectedBytes, { - create: true, - cidVersion: 1 - })) - .then(() => mfs.read(fileName)) - .then(actualBytes => { - expect(actualBytes).to.deep.equal(expectedBytes) - }) + + expect((await cidAtPath(directoryPath, mfs)).version).to.equal(0) + + await mfs.write(filePath, expectedBytes, { + create: true, + cidVersion: 1 + }) + + expect((await cidAtPath(filePath, mfs)).version).to.equal(1) + + const actualBytes = await mfs.read(filePath) + + expect(actualBytes).to.deep.equal(expectedBytes) + }) + + it('overwrites a file with a different CID version', async () => { + const directory = `cid-versions-${Math.random()}` + const directoryPath = `/${directory}` + const fileName = `file-${Math.random()}.txt` + const filePath = `${directoryPath}/${fileName}` + const expectedBytes = Buffer.from([0, 1, 2, 3]) + + await mfs.mkdir(directoryPath, { + cidVersion: 0 + }) + + expect((await cidAtPath(directoryPath, mfs)).version).to.equal(0) + + await mfs.write(filePath, Buffer.from([5, 6]), { + create: true, + cidVersion: 0 + }) + + expect((await cidAtPath(filePath, mfs)).version).to.equal(0) + + await mfs.write(filePath, expectedBytes, { + cidVersion: 1 + }) + + expect((await cidAtPath(filePath, mfs)).version).to.equal(1) + + const actualBytes = await mfs.read(filePath) + + expect(actualBytes).to.deep.equal(expectedBytes) + }) + + it('partially overwrites a file with a different CID version', async () => { + const directory = `cid-versions-${Math.random()}` + const directoryPath = `/${directory}` + const fileName = `file-${Math.random()}.txt` + const filePath = `${directoryPath}/${fileName}` + + await mfs.mkdir(directoryPath, { + cidVersion: 0 + }) + + expect((await cidAtPath(directoryPath, mfs)).version).to.equal(0) + + await mfs.write(filePath, Buffer.from([5, 6, 7, 8, 9, 10, 11]), { + create: true, + cidVersion: 0 + }) + + expect((await cidAtPath(filePath, mfs)).version).to.equal(0) + + await mfs.write(filePath, Buffer.from([0, 1, 2, 3]), { + cidVersion: 1, + offset: 1 + }) + + expect((await cidAtPath(filePath, mfs)).version).to.equal(1) + + const actualBytes = await mfs.read(filePath) + + expect(actualBytes).to.deep.equal(Buffer.from([5, 0, 1, 2, 3, 10, 11])) }) - it.skip('writes a file with a different hash function to the parent', () => { + it('writes a file with a different hash function to the parent', async () => { + const directory = `cid-versions-${Math.random()}` + const directoryPath = `/${directory}` + const fileName = `file-${Math.random()}.txt` + const filePath = `${directoryPath}/${fileName}` + const expectedBytes = Buffer.from([0, 1, 2, 3]) + + await mfs.mkdir(directoryPath, { + cidVersion: 0 + }) + + expect((await cidAtPath(directoryPath, mfs)).version).to.equal(0) + + await mfs.write(filePath, expectedBytes, { + create: true, + cidVersion: 1, + hashAlg: 'sha2-512' + }) + + expect(multihash.decode((await cidAtPath(filePath, mfs)).multihash).name).to.equal('sha2-512') + + const actualBytes = await mfs.read(filePath) + expect(actualBytes).to.deep.equal(expectedBytes) }) })