diff --git a/package.json b/package.json index 2abd096..641156c 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "ipld-dag-cbor": "~0.11.1", "ipld-dag-pb": "~0.11.0", "ipld-eth-star": "^1.4.1", + "ipld-git": "^0.1.0", "is-ipfs": "~0.3.0", "lodash.flatten": "^4.4.0", "lodash.includes": "^4.3.0", @@ -73,4 +74,4 @@ "kumavis ", "wanderer " ] -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index 7023672..3687323 100644 --- a/src/index.js +++ b/src/index.js @@ -16,6 +16,7 @@ const MemoryStore = require('interface-datastore').MemoryDatastore const dagPB = require('ipld-dag-pb') const dagCBOR = require('ipld-dag-cbor') +const ipldGit = require('ipld-git') const ipldEthAccountSnapshot = require('ipld-eth-star').ethAccountSnapshot const ipldEthBlock = require('ipld-eth-star').ethBlock const ipldEthBlockList = require('ipld-eth-star').ethBlockList @@ -55,7 +56,7 @@ class IPLDResolver { } } - // Support by default dag-pb, dag-cbor, and eth-* + // Support by default dag-pb, dag-cbor, git, and eth-* this.support.add(dagPB.resolver.multicodec, dagPB.resolver, dagPB.util) @@ -64,6 +65,10 @@ class IPLDResolver { dagCBOR.resolver, dagCBOR.util) + this.support.add(ipldGit.resolver.multicodec, + ipldGit.resolver, + ipldGit.util) + this.support.add(ipldEthAccountSnapshot.resolver.multicodec, ipldEthAccountSnapshot.resolver, ipldEthAccountSnapshot.util) diff --git a/test/browser.js b/test/browser.js index eb8f507..ac3c679 100644 --- a/test/browser.js +++ b/test/browser.js @@ -40,6 +40,7 @@ describe('Browser', () => { require('./basics')(repo) require('./ipld-dag-pb')(repo) require('./ipld-dag-cbor')(repo) + require('./ipld-git')(repo) require('./ipld-eth-block')(repo) require('./ipld-eth-star')(repo) require('./ipld-all') diff --git a/test/ipld-git.js b/test/ipld-git.js new file mode 100644 index 0000000..f70bf12 --- /dev/null +++ b/test/ipld-git.js @@ -0,0 +1,253 @@ +/* eslint-env mocha */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) +const BlockService = require('ipfs-block-service') +const ipldGit = require('ipld-git') +const series = require('async/series') +const each = require('async/each') +const pull = require('pull-stream') + +const IPLDResolver = require('../src') + +module.exports = (repo) => { + describe('IPLD Resolver with ipld-git', () => { + let resolver + + let blobNode + let treeNode + let commitNode + let commit2Node + let tagNode + + let blobCid + let treeCid + let commitCid + let commit2Cid + let tagCid + + before((done) => { + const bs = new BlockService(repo) + + resolver = new IPLDResolver(bs) + + series([ + (cb) => { + blobNode = new Buffer('626c6f62203800736f6d6564617461', 'hex') // blob 8\0somedata + + ipldGit.util.cid(blobNode, (err, cid) => { + expect(err).to.not.exist() + blobCid = cid + cb() + }) + }, + (cb) => { + treeNode = { + somefile: { + hash: {'/': blobCid.buffer}, + mode: '100644' + } + } + + ipldGit.util.cid(treeNode, (err, cid) => { + expect(err).to.not.exist() + treeCid = cid + cb() + }) + }, + (cb) => { + commitNode = { + gitType: 'commit', + tree: {'/': treeCid.buffer}, + parents: [], + author: { + name: 'John Doe', + email: 'johndoe@example.com', + date: '1497302532 +0200' + }, + committer: { + name: 'John Doe', + email: 'johndoe@example.com', + date: '1497302532 +0200' + }, + message: 'Initial commit\n' + } + + ipldGit.util.cid(commitNode, (err, cid) => { + expect(err).to.not.exist() + commitCid = cid + cb() + }) + }, + (cb) => { + commit2Node = { + gitType: 'commit', + tree: {'/': treeCid.buffer}, + parents: [ + {'/': commitCid.buffer} + ], + author: { + name: 'John Doe', + email: 'johndoe@example.com', + date: '1497302533 +0200' + }, + committer: { + name: 'John Doe', + email: 'johndoe@example.com', + date: '1497302533 +0200' + }, + message: 'Change nothing\n' + } + + ipldGit.util.cid(commit2Node, (err, cid) => { + expect(err).to.not.exist() + commit2Cid = cid + cb() + }) + }, + (cb) => { + tagNode = { + gitType: 'tag', + object: {'/': commit2Cid.buffer}, + type: 'commit', + tag: 'v0.0.0', + tagger: { + name: 'John Doe', + email: 'johndoe@example.com', + date: '1497302534 +0200' + }, + message: 'First release\n' + } + + ipldGit.util.cid(tagNode, (err, cid) => { + expect(err).to.not.exist() + tagCid = cid + cb() + }) + } + ], store) + + function store () { + pull( + pull.values([ + { node: blobNode, cid: blobCid }, + { node: treeNode, cid: treeCid }, + { node: commitNode, cid: commitCid }, + { node: commit2Node, cid: commit2Cid }, + { node: tagNode, cid: tagCid } + ]), + pull.asyncMap((nac, cb) => resolver.put(nac.node, { cid: nac.cid }, cb)), + pull.onEnd(done) + ) + } + }) + + describe('internals', () => { + it('resolver._put', (done) => { + each([ + { node: blobNode, cid: blobCid }, + { node: treeNode, cid: treeCid }, + { node: commitNode, cid: commitCid }, + { node: commit2Node, cid: commit2Cid }, + { node: tagNode, cid: tagCid } + ], (nc, cb) => { + resolver._put(nc.cid, nc.node, cb) + }, done) + }) + + it('resolver._get', (done) => { + resolver.put(blobNode, { cid: blobCid }, (err) => { + expect(err).to.not.exist() + resolver.get(blobCid, (err, result) => { + expect(err).to.not.exist() + expect(blobNode.toString('hex')).to.eql(result.value.toString('hex')) + done() + }) + }) + }) + }) + + describe('public api', () => { + it('resolver.put', (done) => { + resolver.put(blobNode, { cid: blobCid }, done) + }) + + it('resolver.get root path', (done) => { + resolver.get(blobCid, '/', (err, result) => { + expect(err).to.not.exist() + + ipldGit.util.cid(result.value, (err, cid) => { + expect(err).to.not.exist() + expect(cid).to.eql(blobCid) + done() + }) + }) + }) + + it('value within 1st node scope', (done) => { + resolver.get(commitCid, 'message', (err, result) => { + expect(err).to.not.exist() + expect(result.value).to.eql('Initial commit\n') + done() + }) + }) + + it('value within nested node scope (commit/tree)', (done) => { + resolver.get(commitCid, 'tree/somefile/mode', (err, result) => { + expect(err).to.not.exist() + expect(result.value).to.eql('100644') + done() + }) + }) + + it('value within nested node scope (commit/tree/blob)', (done) => { + resolver.get(commitCid, 'tree/somefile/hash', (err, result) => { + expect(err).to.not.exist() + expect(blobNode.toString('hex')).to.eql(result.value.toString('hex')) + done() + }) + }) + + it('value within nested node scope (commit/commit/tree/blob)', (done) => { + resolver.get(commit2Cid, 'parents/0/tree/somefile/hash', (err, result) => { + expect(err).to.not.exist() + expect(blobNode.toString('hex')).to.eql(result.value.toString('hex')) + done() + }) + }) + + it('value within nested node scope (tag/commit/commit/tree/blob)', (done) => { + resolver.get(tagCid, 'object/parents/0/tree/somefile/hash', (err, result) => { + expect(err).to.not.exist() + expect(blobNode.toString('hex')).to.eql(result.value.toString('hex')) + done() + }) + }) + + it('resolver.remove', (done) => { + resolver.put(blobNode, { cid: blobCid }, (err) => { + expect(err).to.not.exist() + resolver.get(blobCid, (err, result) => { + expect(err).to.not.exist() + const node = result.value + expect(blobNode.toString('hex')).to.eql(node.toString('hex')) + remove() + }) + }) + + function remove () { + resolver.remove(blobCid, (err) => { + expect(err).to.not.exist() + resolver.get(blobCid, (err) => { + expect(err).to.exist() + done() + }) + }) + } + }) + }) + }) +} diff --git a/test/node.js b/test/node.js index 21a74ae..9e4ed15 100644 --- a/test/node.js +++ b/test/node.js @@ -29,6 +29,7 @@ describe('Node.js', () => { require('./basics')(repo) require('./ipld-dag-pb')(repo) require('./ipld-dag-cbor')(repo) + require('./ipld-git')(repo) require('./ipld-eth-block')(repo) require('./ipld-eth-star')(repo) require('./ipld-all')