-
Notifications
You must be signed in to change notification settings - Fork 124
Adds API for ipfs.files.get. #28
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,20 +6,28 @@ const bs58 = require('bs58') | |
const Readable = require('readable-stream') | ||
const path = require('path') | ||
const fs = require('fs') | ||
const isNode = require('detect-node') | ||
const bl = require('bl') | ||
const concat = require('concat-stream') | ||
const through = require('through2') | ||
|
||
module.exports = (common) => { | ||
describe('.files', () => { | ||
describe.only('.files', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will need to change this. But I can also do it on merge :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agh, I'm guilty of continually doing this. Will correct. :) |
||
let smallFile | ||
let bigFile | ||
let directoryContent | ||
let ipfs | ||
|
||
before((done) => { | ||
smallFile = fs.readFileSync(path.join(__dirname, './data/testfile.txt') | ||
) | ||
bigFile = fs.readFileSync(path.join(__dirname, './data/15mb.random') | ||
) | ||
smallFile = fs.readFileSync(path.join(__dirname, './data/testfile.txt')) | ||
bigFile = fs.readFileSync(path.join(__dirname, './data/15mb.random')) | ||
directoryContent = { | ||
'pp.txt': fs.readFileSync(path.join(__dirname, './data/test-folder/pp.txt')), | ||
'holmes.txt': fs.readFileSync(path.join(__dirname, './data/test-folder/holmes.txt')), | ||
'jungle.txt': fs.readFileSync(path.join(__dirname, './data/test-folder/jungle.txt')), | ||
'alice.txt': fs.readFileSync(path.join(__dirname, './data/test-folder/alice.txt')), | ||
'files/hello.txt': fs.readFileSync(path.join(__dirname, './data/test-folder/files/hello.txt')), | ||
'files/ipfs.txt': fs.readFileSync(path.join(__dirname, './data/test-folder/files/ipfs.txt')) | ||
} | ||
|
||
common.setup((err, _ipfs) => { | ||
expect(err).to.not.exist | ||
|
@@ -100,15 +108,9 @@ module.exports = (common) => { | |
}) | ||
|
||
it('add a nested dir as array', (done) => { | ||
if (!isNode) { | ||
return done() | ||
// can't run this test cause browserify | ||
// can't shim readFileSync in runtime | ||
} | ||
const base = path.join(__dirname, 'data/test-folder') | ||
const content = (name) => ({ | ||
path: `test-folder/${name}`, | ||
content: fs.readFileSync(path.join(base, name)) | ||
content: directoryContent[name] | ||
}) | ||
const emptyDir = (name) => ({ | ||
path: `test-folder/${name}` | ||
|
@@ -138,21 +140,13 @@ module.exports = (common) => { | |
|
||
describe('.createAddStream', () => { | ||
it('stream of valid files and dirs', (done) => { | ||
if (!isNode) { | ||
return done() | ||
// can't run this test cause browserify | ||
// can't shim readFileSync in runtime | ||
} | ||
|
||
const base = path.join(__dirname, 'data/test-folder') | ||
const content = (name) => ({ | ||
path: `test-folder/${name}`, | ||
content: fs.readFileSync(path.join(base, name)) | ||
content: directoryContent[name] | ||
}) | ||
const emptyDir = (name) => ({ | ||
path: `test-folder/${name}` | ||
}) | ||
|
||
const files = [ | ||
content('pp.txt'), | ||
content('holmes.txt'), | ||
|
@@ -241,7 +235,7 @@ module.exports = (common) => { | |
}) | ||
|
||
describe('.cat', () => { | ||
it('with a bas58 multihash encoded string', () => { | ||
it('with a base58 multihash encoded string', () => { | ||
const hash = 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB' | ||
|
||
return ipfs.cat(hash) | ||
|
@@ -273,11 +267,165 @@ module.exports = (common) => { | |
const hash = new Buffer(bs58.decode('QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB')) | ||
return ipfs.cat(hash) | ||
.then((stream) => { | ||
stream.pipe(bl((err, bldata) => { | ||
stream.pipe(bl((err, data) => { | ||
expect(err).to.not.exist | ||
expect(bldata.toString()).to.contain('Check out some of the other files in this directory:') | ||
expect(data.toString()).to.contain('Check out some of the other files in this directory:') | ||
})) | ||
}) | ||
}) | ||
}) | ||
}) | ||
|
||
describe('.get', () => { | ||
it('with a base58 encoded multihash', (done) => { | ||
const hash = 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB' | ||
ipfs.files.get(hash, (err, stream) => { | ||
expect(err).to.not.exist | ||
stream.pipe(concat((files) => { | ||
expect(err).to.not.exist | ||
expect(files).to.be.length(1) | ||
expect(files[0].path).to.equal(hash) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems that here you expect that the path is a string b58 encoded multihash, while... -> There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The correct thing to do is to check for the bs58-encoded value. If you're seeing anything else it's definitely an error to accommodate pre-this-PR. Thanks for noticing. |
||
files[0].content.pipe(concat((content) => { | ||
expect(content.toString()).to.contain('Check out some of the other files in this directory:') | ||
done() | ||
})) | ||
})) | ||
}) | ||
}) | ||
|
||
it('with a multihash', (done) => { | ||
const hash = 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB' | ||
const mhBuf = new Buffer(bs58.decode(hash)) | ||
ipfs.files.get(mhBuf, (err, stream) => { | ||
expect(err).to.not.exist | ||
stream.pipe(concat((files) => { | ||
expect(files).to.be.length(1) | ||
expect(files[0].path).to.deep.equal(hash) | ||
files[0].content.pipe(concat((content) => { | ||
expect(content.toString()).to.contain('Check out some of the other files in this directory:') | ||
done() | ||
})) | ||
})) | ||
}) | ||
}) | ||
|
||
it('large file', (done) => { | ||
const hash = 'Qme79tX2bViL26vNjPsF3DP1R9rMKMvnPYJiKTTKPrXJjq' | ||
ipfs.files.get(hash, (err, stream) => { | ||
expect(err).to.not.exist | ||
|
||
// accumulate the files and their content | ||
var files = [] | ||
stream.pipe(through.obj((file, enc, next) => { | ||
file.content.pipe(concat((content) => { | ||
files.push({ | ||
path: file.path, | ||
content: content | ||
}) | ||
next() | ||
})) | ||
}, () => { | ||
expect(files.length).to.equal(1) | ||
expect(files[0].path).to.equal(hash) | ||
expect(files[0].content).to.deep.equal(bigFile) | ||
done() | ||
})) | ||
}) | ||
}) | ||
|
||
it('directory', (done) => { | ||
const hash = 'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP' | ||
ipfs.files.get(hash, (err, stream) => { | ||
expect(err).to.not.exist | ||
|
||
// accumulate the files and their content | ||
var files = [] | ||
stream.pipe(through.obj((file, enc, next) => { | ||
if (file.content) { | ||
file.content.pipe(concat((content) => { | ||
files.push({ | ||
path: file.path, | ||
content: content | ||
}) | ||
next() | ||
})) | ||
} else { | ||
files.push(file) | ||
next() | ||
} | ||
}, () => { | ||
// Check paths | ||
var paths = files.map((file) => { | ||
return file.path | ||
}) | ||
expect(paths).to.deep.equal([ | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the path also include the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is how js-ipfs-unixfs-engine works. Is there a specific concern you have? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm just trying to understand if there is a good reason why we should always patch the hash to the path or no. What will the user expect? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think since this is the Core API we have to worry less about what the user expects and more about what would be the most useful to implementation developers, since they'll be the ones who ultimately decide what the users see. They could choose to cull the root hash from the result if they wanted. My thinking is that, as an IPFS implementation developer, I'd want the root hash when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That idea grew on me :) Thank you! |
||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/alice.txt', | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/empty-folder', | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/files', | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/files/empty', | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/files/hello.txt', | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/files/ipfs.txt', | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/holmes.txt', | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/jungle.txt', | ||
'QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP/pp.txt' | ||
]) | ||
|
||
// Check contents | ||
var contents = files.map((file) => { | ||
return file.content ? file.content : null | ||
}) | ||
expect(contents).to.deep.equal([ | ||
null, | ||
directoryContent['alice.txt'], | ||
null, | ||
null, | ||
null, | ||
directoryContent['files/hello.txt'], | ||
directoryContent['files/ipfs.txt'], | ||
directoryContent['holmes.txt'], | ||
directoryContent['jungle.txt'], | ||
directoryContent['pp.txt'] | ||
]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's verify also the content (one chunk out of order is enough to screw the file up) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. I added the directory data to the brfs file reading so we can test this in the browser too. 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sweet! |
||
done() | ||
})) | ||
}) | ||
}) | ||
|
||
describe('promise', () => { | ||
it('with a base58 encoded string', (done) => { | ||
const hash = 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB' | ||
ipfs.files.get(hash) | ||
.then((stream) => { | ||
stream.pipe(concat((files) => { | ||
expect(files).to.be.length(1) | ||
expect(files[0].path).to.equal(hash) | ||
files[0].content.pipe(concat((content) => { | ||
expect(content.toString()).to.contain('Check out some of the other files in this directory:') | ||
done() | ||
})) | ||
})) | ||
}) | ||
.catch((err) => { | ||
expect(err).to.not.exist | ||
}) | ||
}) | ||
|
||
it('errors on invalid key', (done) => { | ||
const hash = 'somethingNotMultihash' | ||
ipfs.files.get(hash) | ||
.then((stream) => {}) | ||
.catch((err) => { | ||
expect(err).to.exist | ||
const errString = err.toString() | ||
if (errString === 'Error: invalid ipfs ref path') { | ||
expect(err.toString()).to.contain('Error: invalid ipfs ref path') | ||
} | ||
if (errString === 'Error: Invalid Key') { | ||
expect(err.toString()).to.contain('Error: Invalid Key') | ||
} | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@noffle seems that this was never added to the files.md. Maybe a missing commit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure where it got dropped. Thanks for noticing! I'll re-add.