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

Commit

Permalink
wip: migrate importer to async IPLD format interface
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddias committed Oct 26, 2016
1 parent 8778c81 commit f4082d5
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 190 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ IPFS unixFS Engine
- [Contribute](#contribute)
- [License](#license)

## BEWARE BEWARE BEWARE there might be 🐉

This module has passed through several iterations and still is far from a nice and easy understandable codebase. Currently missing features:

- tar importer
- trickle dag exporter
- sharding

## Install

With [npm](https://npmjs.org/) installed, run
Expand Down
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ipfs-unixfs-engine",
"version": "0.11.4",
"description": "JavaScript implementation of the unixfs Engine used by IPFS",
"main": "src/index.js",
"main": "lib/index.js",
"jsnext:main": "src/index.js",
"scripts": {
"lint": "aegir-lint",
Expand Down Expand Up @@ -34,13 +34,13 @@
},
"homepage": "https://github.com/ipfs/js-ipfs-unixfs-engineg#readme",
"devDependencies": {
"aegir": "^8.0.1",
"aegir": "^8.1.2",
"buffer-loader": "0.0.1",
"chai": "^3.5.0",
"fs-pull-blob-store": "^0.3.0",
"idb-pull-blob-store": "^0.4.0",
"ipfs-block-service": "^0.5.0",
"ipfs-repo": "^0.9.0",
"fs-pull-blob-store": "^0.4.1",
"idb-pull-blob-store": "^0.5.1",
"ipfs-block-service": "^0.6.0",
"ipfs-repo": "^0.10.0",
"ncp": "^2.0.0",
"pre-commit": "^1.1.3",
"pull-zip": "^2.0.0",
Expand All @@ -49,8 +49,10 @@
"run-series": "^1.1.4"
},
"dependencies": {
"ipld-dag-pb": "^0.0.1",
"cids": "^0.2.0",
"ipfs-unixfs": "^0.1.4",
"ipld-dag-pb": "^0.1.2",
"ipld-resolver": "^0.1.1",
"is-ipfs": "^0.2.0",
"multihashes": "^0.2.2",
"pull-block": "^1.0.2",
Expand Down
7 changes: 0 additions & 7 deletions src/chunker-fixed-size.js

This file was deleted.

7 changes: 7 additions & 0 deletions src/chunker/fixed-size.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict'

const pullBlock = require('pull-block')

module.exports = (size) => {
return pullBlock(size, { zeroPadding: false })
}
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions src/exporter.js → src/exporter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ const traverse = require('pull-traverse')
const pull = require('pull-stream')
const CID = require('cids')

const util = require('./util')
const util = require('./../util')
const switchType = util.switchType
const cleanMultihash = util.cleanMultihash

const dirExporter = require('./exporters/dir')
const fileExporter = require('./exporters/file')
const dirExporter = require('./dir')
const fileExporter = require('./file')

module.exports = (hash, ipldResolver, options) => {
hash = cleanMultihash(hash)
Expand Down
182 changes: 182 additions & 0 deletions src/importer/flush-tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
'use strict'

const mh = require('multihashes')
const UnixFS = require('ipfs-unixfs')
const CID = require('cids')
const dagPB = require('ipld-dag-pb')
const asyncEach = require('async/each')

const DAGLink = dagPB.DAGLink
const DAGNode = dagPB.DAGNode

module.exports = (files, ipldResolver, source, callback) => {
// 1) convert files to a tree
const fileTree = createTree(files)

if (Object.keys(fileTree).length === 0) {
return callback()// no dirs to be created
}

// 2) create sizeIndex
const sizeIndex = createSizeIndex(files)

// 3) bottom up flushing
traverse(fileTree, sizeIndex, null, ipldResolver, source, callback)
}

/*
* createTree
*
* received an array of files with the format:
* {
* path: // full path
* multihash: // multihash of the dagNode
* size: // cumulative size
* }
*
* returns a JSON object that represents a tree where branches are the paths
* and the leaves are objects with file names and respective multihashes, such
* as:
* {
* foo: {
* bar: {
* baz.txt: <multihash>
* }
* }
* }
*/
function createTree (files) {
const fileTree = {}

files.forEach((file) => {
let splitted = file.path.split('/')
if (splitted.length === 1) {
return // adding just one file
}
if (splitted[0] === '') {
splitted = splitted.slice(1)
}
var tmpTree = fileTree

for (var i = 0; i < splitted.length; i++) {
if (!tmpTree[splitted[i]]) {
tmpTree[splitted[i]] = {}
}
if (i === splitted.length - 1) {
tmpTree[splitted[i]] = file.multihash
} else {
tmpTree = tmpTree[splitted[i]]
}
}
})

return fileTree
}

/*
* create a size index that goes like:
* { <multihash>: <size> }
*/
function createSizeIndex (files) {
const sizeIndex = {}

files.forEach((file) => {
sizeIndex[mh.toB58String(file.multihash)] = file.size
})

return sizeIndex
}

/*
* expand the branches recursively (depth first), flush them first
* and then traverse through the bottoum up, flushing everynode
*
* Algorithm tl;dr;
* create a dirNode
* Object.keys
* If the value is an Object
* create a dir Node
* Object.keys
* Once finished, add the result as a link to the dir node
* If the value is not an object
* add as a link to the dirNode
*/
function traverse (tree, sizeIndex, path, ipldResolver, source, done) {
const keys = Object.keys(tree)

let tmp = tree

asyncEach(keys, (key, cb) => {
if (isLeaf(tmp[key])) {
cb()
} else {
path = path ? path + '/' + key : key
console.log('->', path)

traverse(tmp[key], sizeIndex, path, ipldResolver, source, (err, multihash) => {
if (err) {
return done(err)
}
tmp[key] = multihash
cb()
})
}
}, () => {
next(tmp, done)
})

function next (tree, cb) {
// at this stage, all keys are multihashes
// create a dir node
// add all the multihashes as links
// return this new node multihash

const keys = Object.keys(tree)

const ufsDir = new UnixFS('directory')
const node = new DAGNode(ufsDir.marshal())

keys.forEach((key) => {
const b58mh = mh.toB58String(tree[key])
const link = new DAGLink(key, sizeIndex[b58mh], tree[key])
node.addRawLink(link)
})

console.log('0---->', path)
node.multihash((err, multihash) => {
if (err) {
return cb(err)
}
node.size((err, size) => {
if (err) {
return cb(err)
}

sizeIndex[mh.toB58String(multihash)] = size
console.log('1---->', path)

ipldResolver.put({
node: node,
cid: new CID(multihash)
}, (err) => {
if (err) {
source.push(new Error('failed to store dirNode'))
} else if (path) {
console.log('2---->', path)
source.push({
path: path,
multihash: multihash,
size: size
})
}

cb(null, multihash)
})
})
})
}
}

function isLeaf (value) {
return !(typeof value === 'object' && !Buffer.isBuffer(value))
}
Loading

0 comments on commit f4082d5

Please sign in to comment.