From ad1df5a9a121e76872c430e91238ffd14bae94d8 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Mon, 8 Apr 2019 17:53:24 +0100 Subject: [PATCH] feat: handle raw nodes in mfs (#48) Right now we assume that all nodes are `dag-pb` nodes and that they only contain `dag-pb` nodes. This PR allows us to handle `raw` nodes when `stat`ing and `ls`ing IPFS paths. --- src/core/ls-pull-stream.js | 9 ++++++ src/core/stat.js | 13 +++++++++ test/ls.spec.js | 58 ++++++++++++++++++++++++++++++++++++++ test/stat.spec.js | 51 +++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) diff --git a/src/core/ls-pull-stream.js b/src/core/ls-pull-stream.js index ba7e3b3..8d95573 100644 --- a/src/core/ls-pull-stream.js +++ b/src/core/ls-pull-stream.js @@ -109,6 +109,15 @@ module.exports = (context) => { return cb(err) } + if (Buffer.isBuffer(result.node)) { + return cb(null, { + name: file.name, + type: 0, + hash: formatCid(file.cid, options.cidBase), + size: result.node.length + }) + } + const meta = UnixFs.unmarshal(result.node.data) cb(null, { diff --git a/src/core/stat.js b/src/core/stat.js index a7a22ec..f1b3b06 100644 --- a/src/core/stat.js +++ b/src/core/stat.js @@ -63,6 +63,19 @@ module.exports = (context) => { node, cid } = result + if (Buffer.isBuffer(node)) { + return cb(null, { + hash: formatCid(cid, options.cidBase), + size: node.length, + cumulativeSize: node.length, + blocks: 0, + type: 'file', // really? + local: undefined, + sizeLocal: undefined, + withLocality: false + }) + } + const meta = unmarshal(node.data) let blocks = node.links.length diff --git a/test/ls.spec.js b/test/ls.spec.js index 07cbef3..60887b4 100644 --- a/test/ls.spec.js +++ b/test/ls.spec.js @@ -6,6 +6,8 @@ chai.use(require('dirty-chai')) const expect = chai.expect const pull = require('pull-stream/pull') const collect = require('pull-stream/sinks/collect') +const randomBytes = require('./helpers/random-bytes') +const CID = require('cids') const { FILE_TYPES } = require('../src') @@ -17,6 +19,7 @@ const { describe('ls', () => { let mfs + let largeFile = randomBytes(490668) before(async () => { mfs = await createMfs() @@ -216,6 +219,61 @@ describe('ls', () => { } }) + it('lists a raw node', async () => { + const filePath = '/stat/large-file.txt' + + await mfs.write(filePath, largeFile, { + create: true, + parents: true, + rawLeaves: true + }) + + const stats = await mfs.stat(filePath) + const result = await mfs.ipld.get(new CID(stats.hash)) + const node = result.value + const child = node.links[0] + + expect(child.cid.codec).to.equal('raw') + + const rawNodeContents = await mfs.ls(`/ipfs/${child.cid}/`, { + long: true + }) + + expect(rawNodeContents[0].type).to.equal(0) // this is what go does + expect(rawNodeContents[0].hash).to.equal(child.cid.toBaseEncodedString()) + }) + + it('lists a raw node in an mfs directory', async () => { + const filePath = '/stat/large-file.txt' + + await mfs.write(filePath, largeFile, { + create: true, + parents: true, + rawLeaves: true + }) + + const stats = await mfs.stat(filePath) + const cid = new CID(stats.hash) + const result = await mfs.ipld.get(cid) + const node = result.value + const child = node.links[0] + + expect(child.cid.codec).to.equal('raw') + + const dir = `/dir-with-raw-${Date.now()}` + const path = `${dir}/raw-${Date.now()}` + + await mfs.mkdir(dir) + await mfs.cp(`/ipfs/${child.cid.toBaseEncodedString()}`, path) + + const rawNodeContents = await mfs.ls(path, { + long: true + }) + + expect(rawNodeContents[0].type).to.equal(0) // this is what go does + expect(rawNodeContents[0].hash).to.equal(child.cid.toBaseEncodedString()) + }) + it('lists a sharded directory contents', async () => { const shardSplitThreshold = 10 const fileCount = 11 diff --git a/test/stat.spec.js b/test/stat.spec.js index e8338ea..633ed04 100644 --- a/test/stat.spec.js +++ b/test/stat.spec.js @@ -5,6 +5,7 @@ const chai = require('chai') chai.use(require('dirty-chai')) const expect = chai.expect const randomBytes = require('./helpers/random-bytes') +const CID = require('cids') const { createMfs, @@ -153,6 +154,56 @@ describe('stat', () => { expect(stats.type).to.equal('file') }) + it('stats a raw node', async () => { + const filePath = '/stat/large-file.txt' + + await mfs.write(filePath, largeFile, { + create: true, + parents: true, + rawLeaves: true + }) + + const stats = await mfs.stat(filePath) + const result = await mfs.ipld.get(new CID(stats.hash)) + const node = result.value + const child = node.links[0] + + expect(child.cid.codec).to.equal('raw') + + const rawNodeStats = await mfs.stat(`/ipfs/${child.cid.toBaseEncodedString()}`) + + expect(rawNodeStats.hash).to.equal(child.cid.toBaseEncodedString()) + expect(rawNodeStats.type).to.equal('file') // this is what go does + }) + + it('stats a raw node in an mfs directory', async () => { + const filePath = '/stat/large-file.txt' + + await mfs.write(filePath, largeFile, { + create: true, + parents: true, + rawLeaves: true + }) + + const stats = await mfs.stat(filePath) + const result = await mfs.ipld.get(new CID(stats.hash)) + const node = result.value + const child = node.links[0] + + expect(child.cid.codec).to.equal('raw') + + const dir = `/dir-with-raw-${Date.now()}` + const path = `${dir}/raw-${Date.now()}` + + await mfs.mkdir(dir) + await mfs.cp(`/ipfs/${child.cid.toBaseEncodedString()}`, path) + + const rawNodeStats = await mfs.stat(path) + + expect(rawNodeStats.hash).to.equal(child.cid.toBaseEncodedString()) + expect(rawNodeStats.type).to.equal('file') // this is what go does + }) + it('stats a sharded directory', async () => { const shardedDirPath = await createShardedDirectory(mfs)