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

Add files.get command and tests #296

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions src/api/cat.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
'use strict'

const bs58 = require('bs58')
const isIPFS = require('is-ipfs')
const promisify = require('promisify-es6')
const cleanMultihash = require('../clean-multihash')

module.exports = (send) => {
const cat = promisify((multihash, callback) => {
Expand All @@ -15,13 +14,3 @@ module.exports = (send) => {
})
return cat
}

function cleanMultihash (multihash) {
if (!isIPFS.multihash(multihash)) {
throw new Error('not valid multihash')
}
if (Buffer.isBuffer(multihash)) {
return bs58.encode(multihash)
}
return multihash
}
30 changes: 30 additions & 0 deletions src/api/get.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict'

const tarStreamToObjects = require('../tar-stream-to-objects')
const cleanMultihash = require('../clean-multihash')
const promisify = require('promisify-es6')

module.exports = (send) => {
return promisify(function get (path, opts, cb) {
if (typeof opts === 'function' && !cb) {
cb = opts
opts = {}
}

// opts is the real callback -- 'cb' is being injected by promisify
if (typeof opts === 'function' && typeof cb === 'function') {
cb = opts
opts = {}
}

try {
path = cleanMultihash(path)
} catch (err) {
return cb(err)
}

var sendWithTransform = send.withTransform(tarStreamToObjects)

return sendWithTransform('get', path, opts, null, cb)
})
}
15 changes: 15 additions & 0 deletions src/clean-multihash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict'

const bs58 = require('bs58')
const isIPFS = require('is-ipfs')

module.exports = function (multihash) {
if (!isIPFS.multihash(multihash)) {
throw new Error('not valid multihash')
}
if (Buffer.isBuffer(multihash)) {
return bs58.encode(multihash)
}
return multihash
}

7 changes: 7 additions & 0 deletions src/load-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function requireCommands () {
dht: require('./api/dht'),
diag: require('./api/diag'),
id: require('./api/id'),
get: require('./api/get'),
log: require('./api/log'),
ls: require('./api/ls'),
mount: require('./api/mount'),
Expand All @@ -32,6 +33,12 @@ function requireCommands () {
const files = require('./api/files')(send)
files.add = require('./api/add')(send)
files.createAddStream = require('./api/add-stream.js')(send)
files.get = require('./api/get')(send)

// aliases
cmds.add = files.add
cmds.createAddStream = files.createAddStream
cmds.get = files.get

return files
}
Expand Down
32 changes: 32 additions & 0 deletions src/tar-stream-to-objects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict'

const tar = require('tar-stream')
const Readable = require('readable-stream')
const through = require('through2')

// transform tar stream into readable stream of
// { path: 'string', content: Readable }
module.exports = function (err, res, send, done) {

if (err) return done(err)

var ex = tar.extract()
res.pipe(ex)

var objStream = new Readable({ objectMode: true })
objStream._read = function noop () {}

ex.on('entry', function (header, stream, next) {
objStream.push({
path: header.name,
content: header.type !== 'directory' ? stream : null
})
next()
})
ex.on('finish', () => {
objStream.push(null)
})

done(null, objStream)
}

125 changes: 125 additions & 0 deletions test/api/get.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* eslint-env mocha */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these tests cover something that interface-ipfs-core tests don't cover? If yes, why not have all of them at interface-ipfs-core for get?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also getting am error from this file, which makes all the browser tests to fail:

ERROR in ./test/api/get.spec.js
Module build failed: TypeError: Cannot read property 'apply' of undefined

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I get it, these are the tests for the options supported by go-ipfs

/* globals apiClients */
'use strict'

const expect = require('chai').expect
const isNode = require('detect-node')
const fs = require('fs')
const bl = require('bl')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used in this file

const concat = require('concat-stream')
const through = require('through2')

const path = require('path')
const streamEqual = require('stream-equal')

const extract = require('tar-stream').extract
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used


let testfile
let testfileBig

if (isNode) {
testfile = fs.readFileSync(path.join(__dirname, '/../testfile.txt'))
testfileBig = fs.createReadStream(path.join(__dirname, '/../15mb.random'), { bufferSize: 128 })
} else {
testfile = require('raw!../testfile.txt')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use the raw buffer loader anymore, just brfs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meaning, we can use line 21 for both Node.js and browser

}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment here to explain that these are the tests for the options supported by go-ipfs, not yet provided in js-ipfs.

describe('.get', () => {
it('get with no compression args', (done) => {
apiClients.a
.get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', (err, res) => {

// accumulate the files and their content
var files = []
res.pipe(through.obj((file, enc, next) => {
file.content.pipe(concat((content) => {
files.push({
path: file.path,
content: content
})
next()
}))
}, () => {
expect(files).to.be.length(1)
expect(files[0].content.toString()).to.contain(testfile.toString())
done()
}))
})
})

it('get with archive true', (done) => {
apiClients.a
.get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {archive: true}, (err, res) => {

// accumulate the files and their content
var files = []
res.pipe(through.obj((file, enc, next) => {
file.content.pipe(concat((content) => {
files.push({
path: file.path,
content: content
})
next()
}))
}, () => {
expect(files).to.be.length(1)
expect(files[0].content.toString()).to.contain(testfile.toString())
done()
}))
})
})

it('get err with out of range compression level', (done) => {
apiClients.a
.get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {compress: true, 'compression-level': 10}, (err, res) => {
expect(err).to.exist
expect(err.toString()).to.equal('Error: Compression level must be between 1 and 9')
done()
})
})

it('get with compression level', (done) => {
apiClients.a
.get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {compress: true, 'compression-level': 1}, (err, res) => {
expect(err).to.not.exist
done()
})
})

it.skip('get BIG file', (done) => {
if (!isNode) {
return done()
}

apiClients.a.get('Qme79tX2bViL26vNjPsF3DP1R9rMKMvnPYJiKTTKPrXJjq', (err, res) => {
expect(err).to.not.exist

// Do not blow out the memory of nodejs :)
streamEqual(res, testfileBig, (err, equal) => {
expect(err).to.not.exist
expect(equal).to.be.true
done()
})
})
})

describe('promise', () => {
it.skip('get', (done) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this one be skipped?

return apiClients.a.get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP')
.then((res) => {
let buf = ''
res
.on('error', (err) => {
throw err
})
.on('data', (data) => {
buf += data
})
.on('end', () => {
expect(buf).to.contain(testfile.toString())
done()
})
})
})
})
})