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

Commit

Permalink
Merge pull request #224 from xicombd/feat/files-api-symlinks
Browse files Browse the repository at this point in the history
Add symlink support to feat/files-api
  • Loading branch information
daviddias committed Mar 2, 2016
2 parents 038f37e + 2b5472b commit 524ebfc
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 33 deletions.
16 changes: 8 additions & 8 deletions dist/ipfsapi.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions dist/ipfsapi.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ipfs-api",
"version": "2.13.1",
"version": "2.13.2",
"description": "A client library for the IPFS API",
"main": "src/index.js",
"dependencies": {
Expand Down Expand Up @@ -37,7 +37,7 @@
"gulp": "^3.9.0",
"gulp-bump": "^1.0.0",
"gulp-eslint": "^2.0.0-rc-3",
"gulp-filter": "^3.0.1",
"gulp-filter": "^4.0.0",
"gulp-git": "^1.6.0",
"gulp-load-plugins": "^1.0.0",
"gulp-mocha": "^2.1.3",
Expand Down
48 changes: 36 additions & 12 deletions src/get-files-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ function headers (file) {

if (file.dir) {
header['Content-Type'] = 'application/x-directory'
} else if (file.symlink) {
header['Content-Type'] = 'application/symlink'
} else {
header['Content-Type'] = 'application/octet-stream'
}
Expand Down Expand Up @@ -46,20 +48,41 @@ function loadPaths (opts, file) {
follow: followSymlinks
})

return mg.found.map((name) => {
if (mg.cache[name] === 'FILE') {
return {
path: strip(name, file),
dir: false,
content: fs.createReadStream(name)
return mg.found
.map((name) => {
// symlinks
if (mg.symlinks[name] === true) {
return {
path: strip(name, file),
symlink: true,
dir: false,
content: fs.readlinkSync(name)
}
}
} else {
return {
path: strip(name, file),
dir: true

// files
if (mg.cache[name] === 'FILE') {
return {
path: strip(name, file),
symlink: false,
dir: false,
content: fs.createReadStream(name)
}
}
}
})

// directories
if (mg.cache[name] === 'DIR' || mg.cache[name] instanceof Array) {
return {
path: strip(name, file),
symlink: false,
dir: true
}
}

// files inside symlinks and others
return
})
.filter((file) => !!file) // filter out null files
}

return {
Expand Down Expand Up @@ -88,6 +111,7 @@ function getFilesStream (files, opts) {

return {
path: '',
symlink: false,
dir: false,
content: file
}
Expand Down
2 changes: 1 addition & 1 deletion src/request-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function onRes (buffer, cb) {

const stream = !!res.headers['x-stream-output']
const chunkedObjects = !!res.headers['x-chunked-output']
const isJson = res.headers['content-type'].indexOf('application/json') === 0
const isJson = res.headers['content-type'] && res.headers['content-type'].indexOf('application/json') === 0

if (res.statusCode >= 400 || !res.statusCode) {
const error = new Error(`Server responded with ${res.statusCode}`)
Expand Down
28 changes: 26 additions & 2 deletions test/api/add.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,37 @@ describe('.add', () => {
})
})

it('add a nested dir', (done) => {
it('add a nested dir following symlinks', (done) => {
apiClients['a'].add(path.join(__dirname, '/../test-folder'), { recursive: true }, (err, res) => {
if (isNode) {
expect(err).to.not.exist

const added = res[res.length - 1]
expect(added).to.have.property('Hash', 'QmTDH2RXGn8XyDAo9YyfbZAUXwL1FCr44YJCN9HBZmL9Gj')
expect(added).to.have.property('Hash', 'QmRNjDeKStKGTQXnJ2NFqeQ9oW23WcpbmvCVrpDHgDg3T6')

// check that the symlink was replaced by the target file
const linkPath = 'test-folder/hello-link'
const filePath = 'test-folder/files/hello.txt'
const linkHash = res.filter((e) => e.Name === linkPath)[0].Hash
const fileHash = res.filter((e) => e.Name === filePath)[0].Hash
expect(linkHash).to.equal(fileHash)

done()
} else {
expect(err.message).to.be.equal('Recursive uploads are not supported in the browser')
done()
}
})
})

it('add a nested dir without following symlinks', (done) => {
apiClients['a'].add(path.join(__dirname, '/../test-folder'), { recursive: true, followSymlinks: false }, (err, res) => {
if (isNode) {
expect(err).to.not.exist

const added = res[res.length - 1]
// same hash as the result from the cli (ipfs add test/test-folder -r)
expect(added).to.have.property('Hash', 'QmRArDYd8Rk7Zb7K2699KqmQM1uUoejn1chtEAcqkvjzGg')
done()
} else {
expect(err.message).to.be.equal('Recursive uploads are not supported in the browser')
Expand Down
4 changes: 2 additions & 2 deletions test/api/ls.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('ls', function () {
it('should correctly handle a nonexisting path', function (done) {
if (!isNode) return done()

apiClients['a'].ls('QmTDH2RXGn8XyDAo9YyfbZAUXwL1FCr44YJCN9HBZmL9Gj/folder_that_isnt_there', (err, res) => {
apiClients['a'].ls('QmRNjDeKStKGTQXnJ2NFqeQ9oW23WcpbmvCVrpDHgDg3T6/folder_that_isnt_there', (err, res) => {
expect(err).to.exist
expect(res).to.not.exist
done()
Expand Down Expand Up @@ -56,7 +56,7 @@ describe('ls', function () {
it('should correctly handle a nonexisting path', () => {
if (!isNode) return

return apiClients['a'].ls('QmTDH2RXGn8XyDAo9YyfbZAUXwL1FCr44YJCN9HBZmL9Gj/folder_that_isnt_there')
return apiClients['a'].ls('QmRNjDeKStKGTQXnJ2NFqeQ9oW23WcpbmvCVrpDHgDg3T6/folder_that_isnt_there')
.catch((err) => {
expect(err).to.exist
})
Expand Down
19 changes: 19 additions & 0 deletions test/request-api.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,24 @@ describe('ipfsAPI request tests', () => {
protocol: 'http'
}).id(noop)
})

it('does not crash if no content-type header is provided', (done) => {
if (!isNode) {
return done()
}

// go-ipfs always (currently) adds a content-type header, even if no content is present,
// the standard behaviour for an http-api is to omit this header if no content is present
const server = require('http').createServer((req, res) => {
res.writeHead(200)
res.end()
}).listen(6001, () => {
ipfsAPI('/ip4/127.0.0.1/tcp/6001')
.config.replace('test/r-config.json', (err) => {
expect(err).to.not.exist
server.close(done)
})
})
})
})
})
1 change: 1 addition & 0 deletions test/test-folder/hello-link

0 comments on commit 524ebfc

Please sign in to comment.