Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 16d5e7b

Browse files
hugomrdiasachingbrain
authored andcommitted
feat: allow daemon to init and start in a single cmd (#2428)
`ipfs daemon` will now init the repo automatically if one does not exist
1 parent daf40cb commit 16d5e7b

15 files changed

+218
-131
lines changed

.travis.yml

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,58 @@ jobs:
4040
addons:
4141
chrome: stable
4242
script:
43-
- npx aegir test -t browser
44-
- npx aegir test -t webworker
43+
- npx aegir test -t browser -t webworker
4544

4645
- stage: test
4746
name: firefox
4847
addons:
4948
firefox: latest
5049
script:
51-
- npx aegir test -t browser -- --browsers FirefoxHeadless
52-
- npx aegir test -t webworker -- --browsers FirefoxHeadless
50+
- npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless
5351

5452
- stage: test
5553
name: electron-main
54+
os: osx
5655
script:
57-
- xvfb-run npx aegir test -t electron-main -- --bail --timeout 10000
56+
- npx aegir test -t electron-main --bail --timeout 10000
5857

5958
- stage: test
6059
name: electron-renderer
60+
os: osx
6161
script:
62-
- xvfb-run npx aegir test -t electron-renderer -- --bail --timeout 10000
62+
- npx aegir test -t electron-renderer --bail --timeout 10000
63+
64+
- stage: test
65+
name: interop node
66+
script:
67+
- cd node_modules/ipfs-interop
68+
- IPFS_JS_EXEC=./../../src/cli/bin.js IPFS_REUSEPORT=false npx aegir test -t node --bail
69+
70+
- stage: test
71+
name: interop browser
72+
script:
73+
- cd node_modules/ipfs-interop
74+
- IPFS_JS_EXEC=./../../src/cli/bin.js IPFS_REUSEPORT=false npx aegir test -t browser --bail
75+
76+
- stage: test
77+
name: interop electron-main
78+
os: osx
79+
script:
80+
- cd node_modules/ipfs-interop
81+
- IPFS_JS_EXEC=./../../src/cli/bin.js IPFS_REUSEPORT=false npx aegir test -t electron-main -f ./test/node.js --bail --timeout 10000
82+
83+
- stage: test
84+
name: interop electron-renderer
85+
os: osx
86+
script:
87+
- cd node_modules/ipfs-interop
88+
- IPFS_JS_EXEC=./../../src/cli/bin.js IPFS_REUSEPORT=false npx aegir test -t electron-renderer -f ./test/browser.js --bail --timeout 10000
89+
90+
- stage: tag
91+
if: branch = master AND type = push AND fork = false
92+
name: update-last-successful-build
93+
script:
94+
- npx aegir update-last-successful-build
6395

6496
- stage: test
6597
name: interop

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@
9797
"ipfs-bitswap": "~0.25.1",
9898
"ipfs-block": "~0.8.1",
9999
"ipfs-block-service": "~0.15.2",
100-
"ipfs-http-client": "^35.1.0",
100+
"ipfs-http-client": "^37.0.2",
101101
"ipfs-http-response": "~0.3.1",
102102
"ipfs-mfs": "^0.12.2",
103103
"ipfs-multipart": "^0.2.0",
104104
"ipfs-repo": "~0.26.6",
105105
"ipfs-unixfs": "~0.1.16",
106106
"ipfs-unixfs-exporter": "~0.37.7",
107107
"ipfs-unixfs-importer": "~0.39.11",
108-
"ipfs-utils": "~0.2.0",
108+
"ipfs-utils": "~0.4.0",
109109
"ipld": "~0.24.1",
110110
"ipld-bitcoin": "~0.3.0",
111111
"ipld-dag-cbor": "~0.15.0",
@@ -124,7 +124,7 @@
124124
"it-to-stream": "^0.1.1",
125125
"just-safe-set": "^2.1.0",
126126
"kind-of": "^6.0.2",
127-
"ky": "~0.13.0",
127+
"ky": "~0.14.0",
128128
"ky-universal": "~0.3.0",
129129
"libp2p": "~0.26.1",
130130
"libp2p-bootstrap": "~0.9.3",
@@ -188,7 +188,7 @@
188188
"yargs-promise": "^1.1.0"
189189
},
190190
"devDependencies": {
191-
"aegir": "^20.1.0",
191+
"aegir": "^20.3.1",
192192
"base64url": "^3.0.1",
193193
"chai": "^4.2.0",
194194
"clear-module": "^4.0.0",
@@ -199,16 +199,17 @@
199199
"execa": "^2.0.4",
200200
"form-data": "^2.5.1",
201201
"hat": "0.0.3",
202-
"interface-ipfs-core": "^0.113.0",
202+
"interface-ipfs-core": "~0.114.0",
203203
"ipfs-interop": "~0.1.0",
204-
"ipfsd-ctl": "~0.46.0",
204+
"ipfsd-ctl": "^0.47.2",
205205
"libp2p-websocket-star": "~0.10.2",
206206
"ncp": "^2.0.0",
207207
"p-event": "^4.1.0",
208208
"qs": "^6.5.2",
209209
"rimraf": "^3.0.0",
210210
"sinon": "^7.4.2",
211-
"stream-to-promise": "^2.2.0"
211+
"stream-to-promise": "^2.2.0",
212+
"temp-write": "^4.0.0"
212213
},
213214
"optionalDependencies": {
214215
"prom-client": "^11.5.3",

src/cli/commands/daemon.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
'use strict'
22

33
const os = require('os')
4+
const fs = require('fs')
45
const toUri = require('multiaddr-to-uri')
56
const { ipfsPathHelp } = require('../utils')
67
const { isTest } = require('ipfs-utils/src/env')
8+
const debug = require('debug')('ipfs:cli:daemon')
79

810
module.exports = {
911
command: 'daemon',
@@ -13,6 +15,10 @@ module.exports = {
1315
builder (yargs) {
1416
return yargs
1517
.epilog(ipfsPathHelp)
18+
.option('init-config', {
19+
type: 'string',
20+
desc: 'Path to existing configuration file to be loaded during --init.'
21+
})
1622
.option('enable-sharding-experiment', {
1723
type: 'boolean',
1824
default: false
@@ -42,9 +48,22 @@ module.exports = {
4248

4349
const repoPath = argv.getRepoPath()
4450

51+
let config = {}
52+
// read and parse config file
53+
if (argv.initConfig) {
54+
try {
55+
const raw = fs.readFileSync(argv.initConfig)
56+
config = JSON.parse(raw)
57+
} catch (error) {
58+
debug(error)
59+
throw new Error('Default config couldn\'t be found or content isn\'t valid JSON.')
60+
}
61+
}
62+
4563
// Required inline to reduce startup time
4664
const Daemon = require('../../cli/daemon')
4765
const daemon = new Daemon({
66+
config,
4867
silent: argv.silent,
4968
repo: process.env.IPFS_PATH,
5069
offline: argv.offline,

src/cli/commands/init.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
'use strict'
22

3+
const fs = require('fs')
4+
const debug = require('debug')('ipfs:cli:init')
35
const { ipfsPathHelp } = require('../utils')
46

57
module.exports = {
6-
command: 'init [config] [options]',
8+
command: 'init [default-config] [options]',
79
describe: 'Initialize a local IPFS node',
810
builder (yargs) {
911
return yargs
1012
.epilog(ipfsPathHelp)
11-
.positional('config', {
12-
describe: 'Node config, this should JSON and will be merged with the default config. Check https://github.com/ipfs/js-ipfs#optionsconfig',
13+
.positional('default-config', {
14+
describe: 'Initialize with the given configuration. Path to the config file. Check https://github.com/ipfs/js-ipfs#optionsconfig',
1315
type: 'string'
1416
})
1517
.option('bits', {
@@ -34,6 +36,18 @@ module.exports = {
3436
argv.resolve((async () => {
3537
const path = argv.getRepoPath()
3638

39+
let config = {}
40+
// read and parse config file
41+
if (argv.defaultConfig) {
42+
try {
43+
const raw = fs.readFileSync(argv.defaultConfig)
44+
config = JSON.parse(raw)
45+
} catch (error) {
46+
debug(error)
47+
throw new Error('Default config couldn\'t be found or content isn\'t valid JSON.')
48+
}
49+
}
50+
3751
argv.print(`initializing ipfs node at ${path}`)
3852

3953
// Required inline to reduce startup time
@@ -44,7 +58,7 @@ module.exports = {
4458
repo: new Repo(path),
4559
init: false,
4660
start: false,
47-
config: argv.config || {}
61+
config
4862
})
4963

5064
try {

src/cli/daemon.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Daemon {
5555
}
5656

5757
// start the daemon
58-
const ipfsOpts = Object.assign({ init: false }, this._options, { start: true, libp2p })
58+
const ipfsOpts = Object.assign({ }, this._options, { init: true, start: true, libp2p })
5959
const ipfs = new IPFS(ipfsOpts)
6060

6161
await new Promise((resolve, reject) => {

test/cli/daemon.js

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,35 @@ const os = require('os')
99
const path = require('path')
1010
const hat = require('hat')
1111
const fs = require('fs')
12+
const tempWrite = require('temp-write')
1213
const pkg = require('../../package.json')
1314

1415
const skipOnWindows = isWindows() ? it.skip : it
16+
const daemonReady = (daemon, cb) => {
17+
let r = null
18+
const p = new Promise((resolve, reject) => {
19+
daemon.stdout.on('data', async (data) => {
20+
if (data.toString().includes('Daemon is ready')) {
21+
try {
22+
r = await cb()
23+
} catch (err) {
24+
reject(err)
25+
}
26+
daemon.cancel()
27+
}
28+
})
29+
daemon.stderr.on('data', () => reject(new Error('Daemon didnt start')))
30+
daemon.then(() => resolve(r)).catch(err => {
31+
if (r && err.killed) {
32+
return resolve(r)
33+
}
34+
35+
reject(err)
36+
})
37+
})
1538

39+
return p
40+
}
1641
const checkLock = (repo) => {
1742
// skip on windows
1843
// https://github.com/ipfs/js-ipfsd-ctl/pull/155#issuecomment-326983530
@@ -190,14 +215,6 @@ describe('daemon', () => {
190215
checkLock(repoPath)
191216
})
192217

193-
it('gives error if user hasn\'t run init before', async function () {
194-
this.timeout(100 * 1000)
195-
196-
const err = await ipfs.fail('daemon')
197-
198-
expect(err.stdout).to.include('no initialized ipfs repo found in ' + repoPath)
199-
})
200-
201218
it('should be silent', async function () {
202219
this.timeout(100 * 1000)
203220
await ipfs('init')
@@ -265,4 +282,39 @@ describe('daemon', () => {
265282
expect(err.stdout).to.include(`Node.js version: ${process.versions.node}`)
266283
}
267284
})
285+
286+
it('should init by default', async function () {
287+
this.timeout(100 * 1000)
288+
289+
expect(fs.existsSync(repoPath)).to.be.false()
290+
291+
const daemon = ipfs('daemon')
292+
let stdout = ''
293+
294+
daemon.stdout.on('data', (data) => {
295+
stdout += data.toString('utf8')
296+
297+
if (stdout.includes('Daemon is ready')) {
298+
daemon.kill()
299+
}
300+
})
301+
302+
try {
303+
await daemon
304+
throw new Error('Did not kill process')
305+
} catch (err) {
306+
expect(err.killed).to.be.true()
307+
}
308+
309+
expect(fs.existsSync(repoPath)).to.be.true()
310+
})
311+
312+
it('should init with custom config', async function () {
313+
this.timeout(100 * 1000)
314+
const configPath = tempWrite.sync('{"Addresses": {"API": "/ip4/127.0.0.1/tcp/9999"}}', 'config.json')
315+
const daemon = ipfs(`daemon --init-config ${configPath}`)
316+
317+
const r = await daemonReady(daemon, () => ipfs('config \'Addresses.API\''))
318+
expect(r).to.be.eq('/ip4/127.0.0.1/tcp/9999\n')
319+
})
268320
})

test/cli/init.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ const clean = require('../utils/clean')
88
const hat = require('hat')
99
const ipfsExec = require('../utils/ipfs-exec')
1010
const os = require('os')
11+
const tempWrite = require('temp-write')
1112

1213
describe('init', function () {
13-
this.timeout(40 * 1000)
14+
this.timeout(100 * 1000)
1415

1516
let repoPath
1617
let ipfs
@@ -33,8 +34,6 @@ describe('init', function () {
3334
afterEach(() => clean(repoPath))
3435

3536
it('basic', function () {
36-
this.timeout(40 * 1000)
37-
3837
return ipfs('init').then((out) => {
3938
expect(repoDirSync('blocks')).to.have.length.above(2)
4039
expect(repoExistsSync('config')).to.equal(true)
@@ -48,8 +47,6 @@ describe('init', function () {
4847
})
4948

5049
it('bits', function () {
51-
this.timeout(40 * 1000)
52-
5350
return ipfs('init --bits 1024').then(() => {
5451
expect(repoDirSync('blocks')).to.have.length.above(2)
5552
expect(repoExistsSync('config')).to.equal(true)
@@ -58,8 +55,6 @@ describe('init', function () {
5855
})
5956

6057
it('empty', function () {
61-
this.timeout(40 * 1000)
62-
6358
return ipfs('init --bits 1024 --empty-repo true').then(() => {
6459
expect(repoDirSync('blocks')).to.have.length(2)
6560
expect(repoExistsSync('config')).to.equal(true)
@@ -68,11 +63,18 @@ describe('init', function () {
6863
})
6964

7065
it('should present ipfs path help when option help is received', function (done) {
71-
this.timeout(100 * 1000)
72-
7366
ipfs('init --help').then((res) => {
7467
expect(res).to.have.string('export IPFS_PATH=/path/to/ipfsrepo')
7568
done()
7669
})
7770
})
71+
72+
it('default config argument', () => {
73+
const configPath = tempWrite.sync('{"Addresses": {"API": "/ip4/127.0.0.1/tcp/9999"}}', 'config.json')
74+
return ipfs(`init ${configPath}`).then((res) => {
75+
const configRaw = fs.readFileSync(path.join(repoPath, 'config')).toString()
76+
const config = JSON.parse(configRaw)
77+
expect(config.Addresses.API).to.be.eq('/ip4/127.0.0.1/tcp/9999')
78+
})
79+
})
7880
})

test/core/bitswap.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const waterfall = require('async/waterfall')
1313
const parallel = require('async/parallel')
1414
const Block = require('ipfs-block')
1515
const multiaddr = require('multiaddr')
16-
const isNode = require('detect-node')
16+
const { isNode } = require('ipfs-utils/src/env')
1717
const multihashing = require('multihashing-async')
1818
const CID = require('cids')
1919
const path = require('path')

0 commit comments

Comments
 (0)