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

Commit

Permalink
feat: v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
magik6k authored and daviddias committed Sep 2, 2017
1 parent c02c273 commit 51a9b5e
Show file tree
Hide file tree
Showing 43 changed files with 961 additions and 17 deletions.
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@
},
"homepage": "https://github.com/ipld/js-ipld-git",
"dependencies": {
"async": "^2.3.0",
"cids": "~0.5.0",
"multihashes": "~0.4.5",
"multihashing-async": "~0.4.5",
"async": "^2.5.0",
"cids": "~0.5.1",
"multicodec": "~0.1.9",
"multihashes": "~0.4.8",
"multihashing-async": "~0.4.6",
"smart-buffer": "^3.0.3",
"traverse": "^~0.6.6"
},
"devDependencies": {
"aegir": "^11.0.1",
Expand Down
1 change: 0 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@

exports.util = require('./util.js')
exports.resolver = require('./resolver.js')

144 changes: 140 additions & 4 deletions src/resolver.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,152 @@
'use strict'

const util = require('./util')
const setImmediate = require('async/setImmediate')
const traverse = require('traverse')

exports = module.exports

exports.multicodec = 'git'
exports.multicodec = 'git-raw'

const personInfoPaths = [
'original',
'name',
'email',
'date'
]

exports.resolve = (block, path, callback) => {
setImmediate(() => callback(new Error("not implemented"), null))
if (typeof path === 'function') {
callback = path
path = undefined
}

util.deserialize(block.data, (err, node) => {
if (err) {
return callback(err)
}

if (!path || path === '/') {
return callback(null, {
value: node,
remainderPath: ''
})
}

if (Buffer.isBuffer(node)) { // git blob
return callback(null, {
value: node,
remainderPath: path
})
}

const parts = path.split('/')
const val = traverse(node).get(parts)

if (val) {
return callback(null, {
value: val,
remainderPath: ''
})
}

let value
let len = parts.length

for (let i = 0; i < len; i++) {
const partialPath = parts.shift()

if (Array.isArray(node)) {
value = node[Number(partialPath)]
} if (node[partialPath]) {
value = node[partialPath]
} else {
// can't traverse more
if (!value) {
return callback(new Error('path not available at root'))
} else {
parts.unshift(partialPath)
return callback(null, {
value: value,
remainderPath: parts.join('/')
})
}
}
node = value
}
})
}

exports.tree = (block, options, callback) => {
setImmediate(() => callback(new Error("not implemented"), null))
if (typeof options === 'function') {
callback = options
options = undefined
}

options = options || {}

util.deserialize(block.data, (err, node) => {
if (err) {
return callback(err)
}

if (Buffer.isBuffer(node)) { // git blob
return callback(null, [])
}

let paths = []
switch (node.gitType) {
case 'commit':
paths = [
'message',
'tree'
]

paths = paths.concat(personInfoPaths.map(e => 'author/' + e))
paths = paths.concat(personInfoPaths.map(e => 'committer/' + e))
paths = paths.concat([...node.parents.keys()].map(e => 'parents/' + e))

if (node.encoding) {
paths.push('encoding')
}
break
case 'tag':
paths = [
'object',
'type',
'tag',
'message'
]

if (node.tagger) {
paths = paths.concat(personInfoPaths.map((e) => 'tagger/' + e))
}

break
default: // tree
Object.keys(node).forEach(dir => {
paths.push(dir)
paths.push(dir + '/hash')
paths.push(dir + '/mode')
})
}
callback(null, paths)
})
}

exports.isLink = (block, path, callback) => {
exports.resolve(block, path, (err, result) => {
if (err) {
return callback(err)
}

if (result.remainderPath.length > 0) {
return callback(new Error('path out of scope'))
}

if (typeof result.value === 'object' && result.value['/']) {
callback(null, result.value)
} else {
callback(null, false)
}
})
}
75 changes: 67 additions & 8 deletions src/util.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,78 @@
'use strict'

const setImmediate = require('async/setImmediate')
const waterfall = require('async/waterfall')
const multihashing = require('multihashing-async')
const CID = require('cids')

const CID_GIT_TAG = 0x78
const resolver = require('./resolver')
const gitUtil = require('./util/util')

const commit = require('./util/commit')
const tag = require('./util/tag')
const tree = require('./util/tree')

exports = module.exports

exports.serialize = (dagNode, callback) => {
setImmediate(() => callback(new Error("not implemented"), null))
})
if (dagNode === null) {
setImmediate(() => callback(new Error('dagNode passed to serialize was null'), null))
return
}

if (Buffer.isBuffer(dagNode)) {
if (dagNode.slice(0, 4).toString() === 'blob') {
setImmediate(() => callback(null, dagNode))
} else {
setImmediate(() => callback(new Error('unexpected dagNode passed to serialize'), null))
}
return
}

switch (dagNode.gitType) {
case 'commit':
commit.serialize(dagNode, callback)
break
case 'tag':
tag.serialize(dagNode, callback)
break
default:
// assume tree as a file named 'type' is legal
tree.serialize(dagNode, callback)
}
}

exports.deserialize = (data, callback) => {
let headLen = gitUtil.find(data, 0)
let head = data.slice(0, headLen).toString()
let typeLen = head.match(/([^ ]+) (\d+)/)
if (!typeLen) {
setImmediate(() => callback(new Error('invalid object header'), null))
return
}

exports.deserialize = (dagNode, callback) => {
setImmediate(() => callback(new Error("not implemented"), null))
})
switch (typeLen[1]) {
case 'blob':
callback(null, data)
break
case 'commit':
commit.deserialize(data.slice(headLen + 1), callback)
break
case 'tag':
tag.deserialize(data.slice(headLen + 1), callback)
break
case 'tree':
tree.deserialize(data.slice(headLen + 1), callback)
break
default:
setImmediate(() => callback(new Error('unknown object type ' + typeLen[1]), null))
}
}

exports.cid = (dagNode, callback) => {
setImmediate(() => callback(new Error("not implemented"), null))
})
waterfall([
(cb) => exports.serialize(dagNode, cb),
(serialized, cb) => multihashing(serialized, 'sha1', cb),
(mh, cb) => cb(null, new CID(1, resolver.multicodec, mh))
], callback)
}
89 changes: 89 additions & 0 deletions src/util/commit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use strict'

const setImmediate = require('async/setImmediate')
const SmartBuffer = require('smart-buffer').SmartBuffer
const gitUtil = require('./util')

exports = module.exports

exports.serialize = (dagNode, callback) => {
let lines = []
lines.push('tree ' + gitUtil.cidToSha(dagNode.tree['/']).toString('hex'))
dagNode.parents.forEach((parent) => {
lines.push('parent ' + gitUtil.cidToSha(parent['/']).toString('hex'))
})
lines.push('author ' + gitUtil.serializePersonLine(dagNode.author))
lines.push('committer ' + gitUtil.serializePersonLine(dagNode.committer))
if (dagNode.encoding) {
lines.push('encoding ' + dagNode.encoding)
}
if (dagNode.signature) {
lines.push('gpgsig -----BEGIN PGP SIGNATURE-----')
lines.push(dagNode.signature.text)
lines.push(' -----END PGP SIGNATURE-----')
}
lines.push('')
lines.push(dagNode.message)

let data = lines.join('\n')

let outBuf = new SmartBuffer()
outBuf.writeString('commit ')
outBuf.writeString(data.length.toString())
outBuf.writeUInt8(0)
outBuf.writeString(data)
setImmediate(() => callback(null, outBuf.toBuffer()))
}

exports.deserialize = (data, callback) => {
let lines = data.toString().split('\n')
let res = {gitType: 'commit', parents: []}

for (let line = 0; line < lines.length; line++) {
let m = lines[line].match(/^([^ ]+) (.+)$/)
if (!m) {
if (lines[line] !== '') {
setImmediate(() => callback(new Error('Invalid commit line ' + line)))
}
res.message = lines.slice(line + 1).join('\n')
break
}

let key = m[1]
let value = m[2]
switch (key) {
case 'tree':
res.tree = {'/': gitUtil.shaToCid(new Buffer(value, 'hex'))}
break
case 'committer':
res.committer = gitUtil.parsePersonLine(value)
break
case 'author':
res.author = gitUtil.parsePersonLine(value)
break
case 'parent':
res.parents.push({'/': gitUtil.shaToCid(new Buffer(value, 'hex'))})
break
case 'gpgsig': {
if (value !== '-----BEGIN PGP SIGNATURE-----') {
setImmediate(() => callback(new Error('Invalid commit line ' + line)))
}
res.signature = {}

let startLine = line
for (; line < lines.length - 1; line++) {
if (lines[line + 1] === ' -----END PGP SIGNATURE-----') {
res.signature.text = lines.slice(startLine + 1, line + 1).join('\n')
break
}
}
line++
break
}
default:
res[key] = value
}
}

setImmediate(() => callback(null, res))
}
Loading

0 comments on commit 51a9b5e

Please sign in to comment.