Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slay the Dragon! #165

Merged
merged 8 commits into from
Sep 6, 2017
Merged
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"dependencies": {
"async": "^2.5.0",
"go-ipfs-dep": "0.4.10",
"ipfs-api": "^14.3.1",
"ipfs-api": "^14.3.2",
"multiaddr": "^3.0.0",
"once": "^1.4.0",
"rimraf": "^2.6.1",
Expand Down
60 changes: 43 additions & 17 deletions src/node.js → src/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ function findIpfsExecutable () {
const npm3Path = path.join(appRoot, '../', depPath)
const npm2Path = path.join(appRoot, 'node_modules', depPath)

let npmPath
try {
fs.statSync(npm3Path)
return npm3Path
npmPath = npm3Path
} catch (e) {
return npm2Path
npmPath = npm2Path
}

return npmPath
}

function setConfigValue (node, key, value, callback) {
Expand Down Expand Up @@ -201,11 +204,26 @@ class Node {

callback = once(callback)

// Check if there were explicit options to want or not want. Otherwise,
// assume values will be in the local daemon config
// TODO: This should check the local daemon config
const want = {
gateway: typeof this.opts['Addresses.Gateway'] === 'string'
? this.opts['Addresses.Gateway'].length > 0
: true,
api: typeof this.opts['Addresses.API'] === 'string'
? this.opts['Addresses.API'].length > 0
: true
}

parseConfig(this.path, (err, conf) => {
if (err) {
return callback(err)
}

let output = ''
let returned = false

this.subprocess = this._run(args, {env: this.env}, {
error: (err) => {
// Only look at the last error
Expand All @@ -225,18 +243,28 @@ class Node {
}
},
data: (data) => {
const str = String(data).trim()
const match = str.match(/API server listening on (.*)/)
const gwmatch = str.match(/Gateway (.*) listening on (.*)/)

if (match) {
this._apiAddr = multiaddr(match[1])
this.api = ipfs(match[1])
this.api.apiHost = this.apiAddr.nodeAddress().address
this.api.apiPort = this.apiAddr.nodeAddress().port

if (gwmatch) {
this._gatewayAddr = multiaddr(gwmatch[2])
output += String(data)

const apiMatch = want.api
? output.trim().match(/API server listening on (.*)/)
: true

const gwMatch = want.gateway
? output.trim().match(/Gateway (.*) listening on (.*)/)
: true

if (apiMatch && gwMatch && !returned) {
returned = true

if (want.api) {
this._apiAddr = multiaddr(apiMatch[1])
this.api = ipfs(apiMatch[1])
this.api.apiHost = this.apiAddr.nodeAddress().address
this.api.apiPort = this.apiAddr.nodeAddress().port
}

if (want.gateway) {
this._gatewayAddr = multiaddr(gwMatch[2])
this.api.gatewayHost = this.gatewayAddr.nodeAddress().address
this.api.gatewayPort = this.gatewayAddr.nodeAddress().port
}
Expand All @@ -255,9 +283,7 @@ class Node {
* @returns {undefined}
*/
stopDaemon (callback) {
if (!callback) {
callback = () => {}
}
callback = callback || function noop () {}

if (!this.subprocess) {
return callback()
Expand Down
55 changes: 30 additions & 25 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
const os = require('os')
const join = require('path').join

const Node = require('./node')
const Node = require('./daemon')

// Note how defaultOptions are Addresses.Swarm and not Addresses: { Swarm : <> }
const defaultOptions = {
'Addresses.Swarm': ['/ip4/0.0.0.0/tcp/0'],
'Addresses.Gateway': '',
Expand Down Expand Up @@ -33,6 +34,7 @@ const IpfsDaemonController = {
version (callback) {
(new Node()).version(callback)
},

/**
* Create a new local node.
*
Expand All @@ -47,37 +49,17 @@ const IpfsDaemonController = {
callback = opts
opts = {}
}

if (!callback) {
callback = path
path = process.env.IPFS_PATH ||
join(process.env.HOME ||
process.env.USERPROFILE, '.ipfs')
}
process.nextTick(() => {
callback(null, new Node(path, opts))
})
},
/**
* Create a new disposable node and already start the daemon.
*
* @memberof IpfsDaemonController
* @param {Object} [opts={}]
* @param {function(Error, Node)} callback
* @returns {undefined}
*/
disposableApi (opts, callback) {
if (typeof opts === 'function') {
callback = opts
opts = {}
}
this.disposable(opts, (err, node) => {
if (err) {
return callback(err)
}

node.startDaemon(callback)
})
process.nextTick(() => callback(null, new Node(path, opts)))
},

/**
* Create a new disposable node.
* This means the repo is created in a temporary location and cleaned up on process exit.
Expand All @@ -90,7 +72,7 @@ const IpfsDaemonController = {
disposable (opts, callback) {
if (typeof opts === 'function') {
callback = opts
opts = {}
opts = defaultOptions
}

let options = {}
Expand All @@ -109,6 +91,29 @@ const IpfsDaemonController = {
} else {
node.init((err) => callback(err, node))
}
},

/**
* Create a new disposable node and already started the daemon.
*
* @memberof IpfsDaemonController
* @param {Object} [opts={}]
* @param {function(Error, Node)} callback
* @returns {undefined}
*/
disposableApi (opts, callback) {
if (typeof opts === 'function') {
callback = opts
opts = defaultOptions
}

this.disposable(opts, (err, node) => {
if (err) {
return callback(err)
}

node.startDaemon(callback)
})
}
}

Expand Down
53 changes: 53 additions & 0 deletions test/npm-installs.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* eslint-env mocha */
/* eslint max-nested-callbacks: ["error", 8] */
'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const fs = require('fs')
const rimraf = require('rimraf')
const mkdirp = require('mkdirp')
const path = require('path')

describe('ipfs executable path', () => {
it('has the correct path when installed with npm3', (done) => {
process.env.testpath = '/tmp/ipfsd-ctl-test/node_modules/ipfsd-ctl/lib' // fake __dirname
let npm3Path = '/tmp/ipfsd-ctl-test/node_modules/go-ipfs-dep/go-ipfs'

mkdirp(npm3Path, (err) => {
expect(err).to.not.exist()

fs.writeFileSync(path.join(npm3Path, 'ipfs'))
delete require.cache[require.resolve('../src/daemon.js')]
const Daemon = require('../src/daemon.js')

const node = new Daemon()
expect(node.exec)
.to.eql(path.normalize('/tmp/ipfsd-ctl-test/node_modules/go-ipfs-dep/go-ipfs/ipfs'))
rimraf('/tmp/ipfsd-ctl-test', done)
})
})

it('has the correct path when installed with npm2', (done) => {
process.env.testpath = '/tmp/ipfsd-ctl-test/node_modules/ipfsd-ctl/lib' // fake __dirname
let npm2Path = '/tmp/ipfsd-ctl-test/node_modules/ipfsd-ctl/node_modules/go-ipfs-dep/go-ipfs'

mkdirp(npm2Path, (err) => {
expect(err).to.not.exist()

fs.writeFileSync(path.join(npm2Path, 'ipfs'))
delete require.cache[require.resolve('../src/daemon.js')]
const Daemon = require('../src/daemon.js')

const node = new Daemon()

expect(node.exec)
.to.eql(
path.normalize('/tmp/ipfsd-ctl-test/node_modules/ipfsd-ctl/node_modules/go-ipfs-dep/go-ipfs/ipfs')
)
rimraf('/tmp/ipfsd-ctl-test', done)
})
})
})
Loading