diff --git a/package.json b/package.json index af777932e2..0ae51a9e15 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "rimraf": "^2.4.4", "standard": "^5.4.1", "transform-loader": "^0.2.3", - "webpack": "diasdavid/webpack#81f5994" + "webpack": "^2.0.5-beta" }, "dependencies": { "bl": "^1.0.0", @@ -67,7 +67,7 @@ "debug": "^2.2.0", "hapi": "^12.0.0", "ipfs-blocks": "^0.1.0", - "ipfs-merkle-dag": "^0.1.1", + "ipfs-merkle-dag": "^0.2.1", "ipfs-repo": "^0.5.0", "lodash.get": "^4.0.0", "lodash.set": "^4.0.0", diff --git a/src/cli/commands/config.js b/src/cli/commands/config.js index 196eb0c388..22c6b788a3 100644 --- a/src/cli/commands/config.js +++ b/src/cli/commands/config.js @@ -24,7 +24,7 @@ module.exports = Command.extend({ run: (bool, json, key, value) => { if (!key) { - throw new Error('argument \'key\' is required') + throw new Error("argument 'key' is required") } var node = new IPFS() diff --git a/src/ipfs-core/index.js b/src/ipfs-core/index.js index 367bc04dae..9d131a5850 100644 --- a/src/ipfs-core/index.js +++ b/src/ipfs-core/index.js @@ -2,10 +2,12 @@ const defaultRepo = require('./default-repo') // const bl = require('bl') -// const MerkleDAG = require('ipfs-merkle-dag') const blocks = require('ipfs-blocks') const BlockService = blocks.BlockService -// const Block = MerkleDAG.Block +const Block = blocks.Block +const mDAG = require('ipfs-merkle-dag') +const DAGNode = mDAG.DAGNode +const DAGService = mDAG.DAGService exports = module.exports = IPFS @@ -17,7 +19,8 @@ function IPFS (repo) { if (!repo) { repo = defaultRepo() } - const bs = new BlockService(repo) + const blockS = new BlockService(repo) + const dagS = new DAGService(blockS) this.daemon = callback => { // 1. read repo to get peer data @@ -133,16 +136,16 @@ function IPFS (repo) { this.block = { get: (multihash, callback) => { - bs.getBlock(multihash, callback) + blockS.getBlock(multihash, callback) }, put: (block, callback) => { - bs.addBlock(block, callback) + blockS.addBlock(block, callback) }, del: (multihash, callback) => { - bs.deleteBlock(multihash, callback) + blockS.deleteBlock(multihash, callback) }, stat: (multihash, callback) => { - bs.getBlock(multihash, (err, block) => { + blockS.getBlock(multihash, (err, block) => { if (err) { return callback(err) } @@ -153,4 +156,131 @@ function IPFS (repo) { }) } } + + this.object = { + new: (template, callback) => { + if (!callback) { + callback = template + } + var node = new DAGNode() + var block = new Block(node.marshal()) + blockS.addBlock(block, function (err) { + if (err) { + return callback(err) + } + callback(null, { + Hash: block.key, + Size: node.size(), + Name: '' + }) + }) + }, + patch: { + appendData: (multihash, data, callback) => { + this.object.get(multihash, (err, obj) => { + if (err) { return callback(err) } + obj.data = Buffer.concat([obj.data, data]) + dagS.add(obj, (err) => { + if (err) { + return callback(err) + } + callback(null, obj.multihash()) + }) + }) + }, + addLink: (multihash, link, callback) => { + this.object.get(multihash, (err, obj) => { + if (err) { return callback(err) } + obj.addRawLink(link) + dagS.add(obj, (err) => { + if (err) { + return callback(err) + } + callback(null, obj.multihash()) + }) + }) + }, + rmLink: (multihash, multihashLink, callback) => { + this.object.get(multihash, (err, obj) => { + if (err) { return callback(err) } + obj.links = obj.links.filter((link) => { + if (link.hash.equals(multihashLink)) { + return false + } + return true + }) + dagS.add(obj, (err) => { + if (err) { + return callback(err) + } + callback(null, obj.multihash()) + }) + }) + }, + setData: (multihash, data, callback) => { + this.object.get(multihash, (err, obj) => { + if (err) { return callback(err) } + obj.data = data + dagS.add(obj, (err) => { + if (err) { + return callback(err) + } + callback(null, obj.multihash()) + }) + }) + } + }, + data: (multihash, callback) => { + this.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + callback(null, obj.data) + }) + }, + links: (multihash, callback) => { + this.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + callback(null, obj.links) + }) + }, + get: (multihash, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + dagS.get(multihash, callback) + }, + put: (dagNode, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + dagS.add(dagNode, callback) + }, + stat: (multihash, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + + this.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + var res = { + NumLinks: obj.links.length, + BlockSize: obj.marshal().length, + LinksSize: obj.links.reduce((prev, link) => { + return prev + link.size + }, 0), + DataSize: obj.data.length, + CumulativeSize: '' + } + callback(null, res) + }) + } + } } diff --git a/tests/repo-example/blocks/12203aa9/12203aa913048b2ef582d4ee2bf6eccad869e2ae1d9e41a2df4e086fe2e1403e8a5b.data b/tests/repo-example/blocks/12203aa9/12203aa913048b2ef582d4ee2bf6eccad869e2ae1d9e41a2df4e086fe2e1403e8a5b.data new file mode 100644 index 0000000000..ed8c782e45 --- /dev/null +++ b/tests/repo-example/blocks/12203aa9/12203aa913048b2ef582d4ee2bf6eccad869e2ae1d9e41a2df4e086fe2e1403e8a5b.data @@ -0,0 +1,3 @@ +/ +" wҢ���x�G�ܙ��}X������� ��yZdirect�T2 +" �˧7Fw�}�|ɣ�*�#��'V>�|� recursive�T \ No newline at end of file diff --git a/tests/repo-example/blocks/122048b2/122048b220016f4051d7dd74315bf1ffcb1454f0dd7ae43df2dde01bef8a8bdae446.data b/tests/repo-example/blocks/122048b2/122048b220016f4051d7dd74315bf1ffcb1454f0dd7ae43df2dde01bef8a8bdae446.data new file mode 100644 index 0000000000..4a26a4ac35 --- /dev/null +++ b/tests/repo-example/blocks/122048b2/122048b220016f4051d7dd74315bf1ffcb1454f0dd7ae43df2dde01bef8a8bdae446.data @@ -0,0 +1,3 @@ +/ +" ��!6���1�ص��F��2$`7#u@1�direct�T2 +" ����Hz�8�#3u2�ED� ��ƥ��*Q�KMQ� recursive�T \ No newline at end of file diff --git a/tests/repo-example/blocks/122077d2/122077d2a2b0fc907805a547ea83dc99acff7d5806c086068cad8d9e820dd2f4795a.data b/tests/repo-example/blocks/122077d2/122077d2a2b0fc907805a547ea83dc99acff7d5806c086068cad8d9e820dd2f4795a.data new file mode 100644 index 0000000000..78421c81c2 Binary files /dev/null and b/tests/repo-example/blocks/122077d2/122077d2a2b0fc907805a547ea83dc99acff7d5806c086068cad8d9e820dd2f4795a.data differ diff --git a/tests/repo-example/blocks/12209d6c/12209d6c2be50f706953479ab9df2ce3edca90b68053c00b3004b7f0accbe1e8eedf.data b/tests/repo-example/blocks/12209d6c/12209d6c2be50f706953479ab9df2ce3edca90b68053c00b3004b7f0accbe1e8eedf.data new file mode 100644 index 0000000000..b799cf6b22 Binary files /dev/null and b/tests/repo-example/blocks/12209d6c/12209d6c2be50f706953479ab9df2ce3edca90b68053c00b3004b7f0accbe1e8eedf.data differ diff --git a/tests/repo-example/blocks/1220b0ab/1220b0abba9f487a9f38ed23337532da45448e0cd0e21ec6a5dec62a51c54b4d51d1.data b/tests/repo-example/blocks/1220b0ab/1220b0abba9f487a9f38ed23337532da45448e0cd0e21ec6a5dec62a51c54b4d51d1.data new file mode 100644 index 0000000000..82458cdf71 Binary files /dev/null and b/tests/repo-example/blocks/1220b0ab/1220b0abba9f487a9f38ed23337532da45448e0cd0e21ec6a5dec62a51c54b4d51d1.data differ diff --git a/tests/repo-example/blocks/1220b0cb/1220b0cba7371f11461f77081b947d837cc9a3b80e182ac123bbd427563e8b167c96.data b/tests/repo-example/blocks/1220b0cb/1220b0cba7371f11461f77081b947d837cc9a3b80e182ac123bbd427563e8b167c96.data new file mode 100644 index 0000000000..3dcbfc8443 Binary files /dev/null and b/tests/repo-example/blocks/1220b0cb/1220b0cba7371f11461f77081b947d837cc9a3b80e182ac123bbd427563e8b167c96.data differ diff --git a/tests/repo-example/blocks/1220e586/1220e586199640e1a4c63fa38c5434b9e72dc99d23a391d3db5e1e42d00527241671.data b/tests/repo-example/blocks/1220e586/1220e586199640e1a4c63fa38c5434b9e72dc99d23a391d3db5e1e42d00527241671.data new file mode 100644 index 0000000000..f2bf4f8b8d --- /dev/null +++ b/tests/repo-example/blocks/1220e586/1220e586199640e1a4c63fa38c5434b9e72dc99d23a391d3db5e1e42d00527241671.data @@ -0,0 +1,115 @@ + +� � # 0.1 - Quick Start + +This is a set of short examples with minimal explanation. It is meant as +a "quick start". Soon, we'll write a longer tour :-) + + +Add a file to ipfs: + + echo "hello world" >hello + ipfs add hello + + +View it: + + ipfs cat + + +Try a directory: + + mkdir foo + mkdir foo/bar + echo "baz" > foo/baz + echo "baz" > foo/bar/baz + ipfs add -r foo + + +View things: + + ipfs ls + ipfs ls /bar + ipfs cat /baz + ipfs cat /bar/baz + ipfs cat /bar + ipfs ls /baz + + +References: + + ipfs refs + ipfs refs -r + ipfs refs --help + + +Get: + + ipfs get -o foo2 + diff foo foo2 + + +Objects: + + ipfs object get + ipfs object get /foo2 + ipfs object --help + + +Pin + GC: + + ipfs pin add + ipfs repo gc + ipfs ls + ipfs pin rm + ipfs repo gc + + +Daemon: + + ipfs daemon (in another terminal) + ipfs id + + +Network: + + (must be online) + ipfs swarm peers + ipfs id + ipfs cat + + +Mount: + + (warning: fuse is finicky!) + ipfs mount + cd /ipfs/ + ls + + +Tool: + + ipfs version + ipfs update + ipfs commands + ipfs config --help + open http://localhost:5001/webui + + +Browse: + + webui: + + http://localhost:5001/webui + + video: + + http://localhost:8080/ipfs/QmVc6zuAneKJzicnJpfrqCH9gSy6bz54JhcypfJYhGUFQu/play#/ipfs/QmTKZgRNwDNZwHtJSjCp6r5FYefzpULfy37JvMt9DwvXse + + images: + + http://localhost:8080/ipfs/QmZpc3HvfjEXvLWGQPWbHk3AjD5j8NEN4gmFN8Jmrd5g83/cs + + markdown renderer app: + + http://localhost:8080/ipfs/QmX7M9CiYXjVeFnkfVGf3y5ixTZ2ACeSGyL1vBJY1HvQPp/mdown +� \ No newline at end of file diff --git a/tests/repo-example/blocks/1220f1c1/1220f1c121360796b1c031b0d8b58fd546ab06c601063224601337231b75401a31dd.data b/tests/repo-example/blocks/1220f1c1/1220f1c121360796b1c031b0d8b58fd546ab06c601063224601337231b75401a31dd.data new file mode 100644 index 0000000000..3092e413d6 Binary files /dev/null and b/tests/repo-example/blocks/1220f1c1/1220f1c121360796b1c031b0d8b58fd546ab06c601063224601337231b75401a31dd.data differ diff --git a/tests/repo-example/datastore/MANIFEST-000004 b/tests/repo-example/datastore/MANIFEST-000004 new file mode 100644 index 0000000000..20c00998ea Binary files /dev/null and b/tests/repo-example/datastore/MANIFEST-000004 differ diff --git a/tests/test-cli/test-config.js b/tests/test-cli/test-config.js index 9a3eeca710..c704f2274a 100644 --- a/tests/test-cli/test-config.js +++ b/tests/test-cli/test-config.js @@ -66,7 +66,7 @@ describe('config', () => { it('set a config key with invalid json', done => { nexpect.spawn('node', [process.cwd() + '/src/cli/bin.js', 'config', 'foo', '{"bar: 0}', '--json']) .run((err, stdout, exitcode) => { - const expected = 'error invalid JSON provided' + const expected = 'error\tinvalid JSON provided' expect(stdout[0]).to.equal(expected) expect(err).to.not.exist expect(exitcode).to.equal(1) @@ -77,7 +77,7 @@ describe('config', () => { it('call config with no arguments', done => { nexpect.spawn('node', [process.cwd() + '/src/cli/bin.js', 'config']) .run((err, stdout, exitcode) => { - const expected = 'error argument \'key\' is required' + const expected = "error\targument 'key' is required" expect(stdout[0]).to.equal(expected) expect(err).to.not.exist expect(exitcode).to.equal(1) diff --git a/tests/test-core/browser.js b/tests/test-core/browser.js index aff5aa7833..90f8b73e24 100644 --- a/tests/test-core/browser.js +++ b/tests/test-core/browser.js @@ -7,9 +7,9 @@ const _ = require('lodash') const repoContext = require.context('buffer!./../repo-example', true) const idb = window.indexedDB || - window.mozIndexedDB || - window.webkitIndexedDB || - window.msIndexedDB + window.mozIndexedDB || + window.webkitIndexedDB || + window.msIndexedDB idb.deleteDatabase('ipfs') idb.deleteDatabase('ipfs/blocks') diff --git a/tests/test-core/test-block.js b/tests/test-core/test-block.js index 74594c9397..da808c71be 100644 --- a/tests/test-core/test-block.js +++ b/tests/test-core/test-block.js @@ -61,7 +61,7 @@ describe('block', function () { it('stat', function (done) { const mh = new Buffer(base58 - .decode('QmVtU7ths96fMgZ8YSZAbKghyieq7AjxNdcqyVzxTt3qVe')) + .decode('QmVtU7ths96fMgZ8YSZAbKghyieq7AjxNdcqyVzxTt3qVe')) ipfs.block.stat(mh, (err, stats) => { expect(err).to.not.exist expect(stats.Key.equals(mh)).to.equal(true) diff --git a/tests/test-core/test-config.js b/tests/test-core/test-config.js index f4ec77f895..9a9ceafd22 100644 --- a/tests/test-core/test-config.js +++ b/tests/test-core/test-config.js @@ -90,12 +90,12 @@ describe('config', () => { }) }) - // cli only feature built with show and replace - // it.skip('edit', done => { - // const ipfs = new IPFS() - // ipfs.config((err, config) => { - // expect(err).to.not.exist - // done() - // }) - // }) +// cli only feature built with show and replace +// it.skip('edit', done => { +// const ipfs = new IPFS() +// ipfs.config((err, config) => { +// expect(err).to.not.exist +// done() +// }) +// }) }) diff --git a/tests/test-core/test-object.js b/tests/test-core/test-object.js new file mode 100644 index 0000000000..16dbd80202 --- /dev/null +++ b/tests/test-core/test-object.js @@ -0,0 +1,128 @@ +/* globals describe, before, it */ + +'use strict' + +const expect = require('chai').expect +const IPFS = require('../../src/ipfs-core') +const bs58 = require('bs58') +const mDAG = require('ipfs-merkle-dag') +const DAGNode = mDAG.DAGNode +const DAGLink = mDAG.DAGLink + +// TODO use arrow funtions again when https://github.com/webpack/webpack/issues/1944 is fixed +describe('object', () => { + var ipfs + + before((done) => { + ipfs = new IPFS() + done() + }) + + it('new', (done) => { + ipfs.object.new((err, obj) => { + expect(err).to.not.exist + expect(obj).to.have.property('Size', 0) + expect(obj).to.have.property('Name', '') + expect(obj).to.have.property('Hash') + expect(bs58.encode(obj.Hash).toString()) + .to.equal('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n') + expect(obj.Size).to.equal(0) + done() + }) + }) + + it('patch append-data', (done) => { + const mh = new Buffer(bs58.decode('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG')) + + ipfs.object.patch.appendData(mh, new Buffer('data data'), (err, multihash) => { + expect(err).to.not.exist + expect(mh).to.not.deep.equal(multihash) + done() + }) + }) + + it('patch add-link', (done) => { + const mh = new Buffer(bs58.decode('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG')) + + ipfs.object.patch.addLink(mh, new DAGLink('prev', 0, mh), (err, multihash) => { + expect(err).to.not.exist + expect(mh).to.not.deep.equal(multihash) + done() + }) + }) + + it('patch rm-link', (done) => { + const rmmh = new Buffer(bs58.decode('QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V')) + const mh = new Buffer(bs58.decode('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG')) + + ipfs.object.patch.rmLink(mh, rmmh, (err, multihash) => { + expect(err).to.not.exist + expect(mh).to.not.deep.equal(multihash) + done() + }) + }) + + it('patch set-data', (done) => { + const mh = new Buffer(bs58.decode('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG')) + + ipfs.object.patch.setData(mh, new Buffer('data data data'), (err, multihash) => { + expect(err).to.not.exist + expect(mh).to.not.deep.equal(multihash) + done() + }) + }) + + it('data', (done) => { + const mh = new Buffer(bs58.decode('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG')) + ipfs.object.data(mh, (err, data) => { + expect(err).to.not.exist + expect(data).to.deep.equal(new Buffer('\u0008\u0001')) + done() + }) + }) + + it('links', (done) => { + const mh = new Buffer(bs58.decode('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG')) + ipfs.object.links(mh, (err, links) => { + expect(err).to.not.exist + expect(links.length).to.equal(6) + done() + }) + }) + + it('get', (done) => { + const mh = new Buffer(bs58.decode('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n')) + ipfs.object.get(mh, (err, obj) => { + expect(err).to.not.exist + expect(obj.size()).to.equal(0) + expect(obj).to.have.property('data') + expect(obj).to.have.property('links') + done() + }) + }) + + it('put', (done) => { + const node = new DAGNode(new Buffer('Hello, is it me you are looking for')) + ipfs.object.put(node, (err) => { + expect(err).to.not.exist + done() + }) + }) + + it('stat', (done) => { + const mh = new Buffer(bs58.decode('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG')) + ipfs.object.stat(mh, (err, stats) => { + expect(err).to.not.exist + + var expected = { + NumLinks: 6, + BlockSize: 309, + LinksSize: 6067, + DataSize: 2, + CumulativeSize: '' + } + expect(stats).to.deep.equal(expected) + done() + }) + }) +})