Skip to content
This repository was archived by the owner on Aug 12, 2020. It is now read-only.

Commit 9585a9f

Browse files
committed
data exporting
1 parent 19910e5 commit 9585a9f

File tree

68 files changed

+310
-350
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+310
-350
lines changed

.npmignore

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
.DS_Store
3+
tests/repo-tests*
4+
5+
# Logs
6+
logs
7+
*.log
8+
9+
# Runtime data
10+
pids
11+
*.pid
12+
*.seed
13+
14+
# Directory for instrumented libs generated by jscoverage/JSCover
15+
lib-cov
16+
17+
# Coverage directory used by tools like istanbul
18+
coverage
19+
20+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21+
.grunt
22+
23+
# node-waf configuration
24+
.lock-wscript
25+
26+
# Compiled binary addons (http://nodejs.org/api/addons.html)
27+
build/Release
28+
29+
# Dependency directory
30+
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
31+
node_modules
32+
33+
test

.travis.yml

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
sudo: false
12
language: node_js
23
node_js:
3-
- '4'
4-
- '5'
4+
- 4
5+
- 5
56

7+
# Make sure we have new NPM.
68
before_install:
7-
- npm i -g npm
8-
# Workaround for a permissions issue with Travis virtual machine images
9+
- npm install -g npm
10+
11+
script:
12+
- npm run lint
13+
- npm test
14+
- npm run coverage
915

1016
addons:
1117
firefox: 'latest'
@@ -14,6 +20,5 @@ before_script:
1420
- export DISPLAY=:99.0
1521
- sh -e /etc/init.d/xvfb start
1622

17-
script:
18-
- npm run lint
19-
- npm test
23+
after_success:
24+
- npm run coverage-publish

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ IPFS Data Importing
66
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
77
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
88
[![Build Status](https://travis-ci.org/ipfs/js-ipfs-data-importing.svg?style=flat-square)](https://travis-ci.org/ipfs/js-ipfs-data-importing)
9-
![](https://img.shields.io/badge/coverage-%3F-yellow.svg?style=flat-square)
9+
[![Coverage Status](https://coveralls.io/repos/github/ipfs/js-ipfs-data-importing/badge.svg?branch=master)](https://coveralls.io/github/ipfs/js-ipfs-data-importing?branch=master)
1010
[![Dependency Status](https://david-dm.org/ipfs/js-ipfs-data-importing.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-data-importing)
1111
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
1212

circle.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
machine:
2+
node:
3+
version: stable
4+
5+
dependencies:
6+
pre:
7+
- google-chrome --version
8+
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
9+
- sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
10+
- sudo apt-get update
11+
- sudo apt-get --only-upgrade install google-chrome-stable
12+
- google-chrome --version

package.json

+14-21
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
"name": "ipfs-data-importing",
33
"version": "0.3.3",
44
"description": "JavaScript implementation of the layout and chunking mechanisms used by IPFS",
5-
"main": "src/index.js",
5+
"main": "lib/index.js",
6+
"jsnext:main": "src/index.js",
67
"scripts": {
7-
"lint": "dignified-lint",
8-
"build": "dignified-build",
9-
"test": "dignified-test",
10-
"test:node": "dignified-test node",
11-
"test:browser": "dignified-test browser",
12-
"release": "dignified-release"
8+
"lint": "aegir-lint",
9+
"build": "aegir-build",
10+
"test": "aegir-test",
11+
"test:node": "aegir-test node",
12+
"test:browser": "aegir-test browser",
13+
"release": "aegir-release",
14+
"coverage": "aegir-coverage",
15+
"coverage-publish": "aegir-coverage publish"
1316
},
1417
"pre-commit": [
1518
"lint",
@@ -29,26 +32,16 @@
2932
},
3033
"homepage": "https://github.com/diasdavid/js-ipfs-data-importing#readme",
3134
"devDependencies": {
32-
"brfs": "^1.4.3",
35+
"aegir": "^2.1.1",
3336
"block-stream2": "^1.1.0",
37+
"brfs": "^1.4.3",
3438
"bs58": "^3.0.0",
3539
"buffer-loader": "0.0.1",
36-
"chai": "^3.4.1",
37-
"dignified.js": "^1.0.0",
40+
"chai": "^3.5.0",
3841
"fs-blob-store": "^5.2.1",
3942
"highland": "^2.7.4",
4043
"idb-plus-blob-store": "^1.0.0",
4144
"ipfs-repo": "^0.6.1",
42-
"istanbul": "^0.4.1",
43-
"json-loader": "^0.5.4",
44-
"karma": "^0.13.19",
45-
"karma-chrome-launcher": "^0.2.2",
46-
"karma-cli": "^0.1.2",
47-
"karma-firefox-launcher": "^0.1.7",
48-
"karma-mocha": "^0.2.1",
49-
"karma-sourcemap-loader": "^0.3.7",
50-
"karma-spec-reporter": "0.0.26",
51-
"karma-webpack": "^1.7.0",
5245
"mocha": "^2.3.4",
5346
"ncp": "^2.0.0",
5447
"pre-commit": "^1.1.2",
@@ -61,7 +54,7 @@
6154
"block-stream2": "^1.1.0",
6255
"debug": "^2.2.0",
6356
"ipfs-blocks": "^0.1.2",
64-
"ipfs-merkle-dag": "^0.3.0",
57+
"ipfs-merkle-dag": "^0.4.0",
6558
"ipfs-unixfs": "^0.1.0",
6659
"through2": "^2.0.0"
6760
}

src/index.js

+113-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ const FixedSizeChunker = require('./chunker-fixed-size')
99
const through2 = require('through2')
1010
const UnixFS = require('ipfs-unixfs')
1111
const async = require('async')
12+
const events = require('events')
13+
const Readable = require('stream').Readable
14+
const pathj = require('path')
1215

1316
exports = module.exports
1417

@@ -206,7 +209,6 @@ exports.import = (target, dagService, options, callback) => {
206209
leafSize: raw.fileSize(),
207210
Name: ''
208211
})
209-
210212
cb()
211213
})
212214
}, (cb) => {
@@ -249,6 +251,114 @@ exports.import = (target, dagService, options, callback) => {
249251
// function streamImporter (stream, callback) {}
250252
}
251253

252-
exports.export = function () {
253-
// export into files by hash
254+
exports.export = function (hash, dagService, options, callback) {
255+
if (typeof options === 'function') {
256+
callback = options
257+
options = {}
258+
}
259+
260+
const ee = new events.EventEmitter()
261+
dagService.get(hash, (err, fetchedNode) => {
262+
if (err) {
263+
if (callback) {
264+
return callback(err)
265+
}
266+
return
267+
}
268+
const data = UnixFS.unmarshal(fetchedNode.data)
269+
const type = data.type
270+
if (type === 'directory') {
271+
dirExporter(fetchedNode, hash, callback)
272+
}
273+
if (type === 'file') {
274+
fileExporter(fetchedNode, hash, false, callback)
275+
}
276+
})
277+
return ee
278+
279+
function fileExporter (node, name, dir, callback) {
280+
if (typeof dir === 'function') { callback = dir; dir = {} }
281+
var rs = new Readable()
282+
if (node.links.length === 0) {
283+
const unmarshaledData = UnixFS.unmarshal(node.data)
284+
ee.emit('file', { stream: rs, path: name, dir: dir })
285+
rs.push(unmarshaledData.data)
286+
rs.push(null)
287+
if (callback) {
288+
callback()
289+
}
290+
return
291+
} else {
292+
ee.emit('file', { stream: rs, path: name, dir: dir })
293+
var init = false
294+
rs._read = () => {
295+
if (init) {
296+
return
297+
}
298+
init = true
299+
async.forEachSeries(node.links, (link, callback) => {
300+
dagService.get(link.hash, (err, res) => {
301+
if (err) {
302+
callback(err)
303+
}
304+
var unmarshaledData = UnixFS.unmarshal(res.data)
305+
rs.push(unmarshaledData.data)
306+
callback()
307+
})
308+
}, (err) => {
309+
if (err) {
310+
if (callback) {
311+
return callback(err)
312+
}
313+
return
314+
}
315+
rs.push(null)
316+
if (callback) {
317+
callback()
318+
}
319+
return
320+
})
321+
}
322+
}
323+
}
324+
325+
function dirExporter (node, name, callback) {
326+
var rs = new Readable()
327+
if (node.links.length === 0) {
328+
rs.push(node.data)
329+
rs.push(null)
330+
ee.emit('file', {stream: rs, path: name})
331+
if (callback) {
332+
callback()
333+
}
334+
return
335+
} else {
336+
async.forEachSeries(node.links, (link, callback) => {
337+
dagService.get(link.hash, (err, res) => {
338+
if (err) {
339+
callback(err)
340+
}
341+
var unmarshaledData = UnixFS.unmarshal(res.data)
342+
if (unmarshaledData.type === 'file') {
343+
return (fileExporter(res, pathj.join(name, link.name), callback))
344+
}
345+
if (unmarshaledData.type === 'directory') {
346+
return (dirExporter(res, pathj.join(name, link.name), callback))
347+
}
348+
callback()
349+
})
350+
}, (err) => {
351+
if (err) {
352+
if (callback) {
353+
return callback(err)
354+
}
355+
return
356+
}
357+
if (callback) {
358+
callback()
359+
}
360+
return
361+
})
362+
}
363+
}
254364
}

test/buffer-test.js

+55
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,60 @@ module.exports = function (repo) {
8282
})
8383
})
8484
})
85+
86+
it('export a file with no links', (done) => {
87+
const hash = 'QmQmZQxSKQppbsWfVzBvg59Cn3DKtsNVQ94bjAxg2h3Lb8'
88+
const bs = new BlockService(repo)
89+
const ds = new DAGService(bs)
90+
const testExport = importer.export(hash, ds)
91+
testExport.on('file', (data) => {
92+
ds.get(hash, (err, fetchedNode) => {
93+
expect(err).to.not.exist
94+
const unmarsh = UnixFS.unmarshal(fetchedNode.data)
95+
expect(unmarsh.data).to.deep.equal(data.stream._readableState.buffer[0])
96+
done()
97+
})
98+
})
99+
})
100+
101+
it('export a small file with links', (done) => {
102+
const hash = 'QmW7BDxEbGqxxSYVtn3peNPQgdDXbWkoQ6J1EFYAEuQV3Q'
103+
const bs = new BlockService(repo)
104+
const ds = new DAGService(bs)
105+
const testExport = importer.export(hash, ds)
106+
testExport.on('file', (data) => {
107+
expect(data.stream).to.exist
108+
done()
109+
})
110+
})
111+
112+
it('export a large file > 5mb', (done) => {
113+
const hash = 'QmRQgufjp9vLE8XK2LGKZSsPCFCF6e4iynCQtNB5X2HBKE'
114+
const bs = new BlockService(repo)
115+
const ds = new DAGService(bs)
116+
const testExport = importer.export(hash, ds)
117+
testExport.on('file', (data) => {
118+
expect(data.stream).to.exist
119+
done()
120+
})
121+
})
122+
123+
it('export a directory', (done) => {
124+
const hash = 'QmWChcSFMNcFkfeJtNd8Yru1rE6PhtCRfewi1tMwjkwKjN'
125+
const bs = new BlockService(repo)
126+
const ds = new DAGService(bs)
127+
const testExport = importer.export(hash, ds)
128+
var fs = []
129+
testExport.on('file', (data) => {
130+
fs.push(data)
131+
})
132+
setTimeout(() => {
133+
expect(fs[0].path).to.equal('QmWChcSFMNcFkfeJtNd8Yru1rE6PhtCRfewi1tMwjkwKjN/200Bytes.txt')
134+
expect(fs[1].path).to.equal('QmWChcSFMNcFkfeJtNd8Yru1rE6PhtCRfewi1tMwjkwKjN/dir-another')
135+
expect(fs[2].path).to.equal('QmWChcSFMNcFkfeJtNd8Yru1rE6PhtCRfewi1tMwjkwKjN/level-1/200Bytes.txt')
136+
expect(fs[3].path).to.equal('QmWChcSFMNcFkfeJtNd8Yru1rE6PhtCRfewi1tMwjkwKjN/level-1/level-2')
137+
done()
138+
}, 1000)
139+
})
85140
})
86141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
5
2+
" $��G�,�A�4{���x�Z/.����D`� 200Bytes.txt�/
3+
" Y��9_)a���˹2�R�m�Ŗke�9��level-2
4+


test/repo-example/blocks/122074d4/122074d42168a1c62b4796e77a9591d8f1fab4685f6674eabecc7773913363b45301.data

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
5
2+
" $��G�,�A�4{���x�Z/.����D`� 200Bytes.txt�3
3+
" Y��9_)a���˹2�R�m�Ŗke�9�� dir-another0
4+
" Ty�5;_9Yf�q��F�Lhyl���/��level-1�
5+


test/repo-tests1457120896998/blocks/1220120f/1220120f6af601d46e10b2d2e11ed71c55d25f3042c22501e41d1246e7a1e9d3d8ec.data

-28
This file was deleted.

test/repo-tests1457120896998/blocks/122031e7/122031e7a41c15d03feb8cd793c3348ea3b310512d7767a9abfbd7a928a85e977173.data

-4
This file was deleted.

0 commit comments

Comments
 (0)