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

Commit fee0141

Browse files
hugomrdiasAlan Shaw
authored and
Alan Shaw
committed
fix: move mfs cmds and safer exit (#1981)
This PR moves mfs cli commands to parser.js to make them available for tests and also add `signal-exit` to the cli to make forced exits safer. Co-Authored-By: hugomrdias <[email protected]>
1 parent 1fd2227 commit fee0141

File tree

6 files changed

+86
-76
lines changed

6 files changed

+86
-76
lines changed

src/cli/bin.js

Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,79 +3,65 @@
33
/* eslint-disable no-console */
44
'use strict'
55

6-
process.on('uncaughtException', (err) => {
7-
console.info(err)
8-
9-
throw err
6+
// Handle any uncaught errors
7+
process.once('uncaughtException', (err, origin) => {
8+
if (origin === 'uncaughtException') {
9+
console.error(err)
10+
process.exit(1)
11+
}
1012
})
11-
12-
process.on('unhandledRejection', (err) => {
13-
console.info(err)
14-
15-
throw err
13+
process.once('unhandledRejection', (err) => {
14+
console.error(err)
15+
process.exit(1)
1616
})
1717

1818
const semver = require('semver')
1919
const pkg = require('../../package.json')
20-
20+
// Check for node version
2121
if (!semver.satisfies(process.versions.node, pkg.engines.node)) {
2222
console.error(`Please update your Node.js version to ${pkg.engines.node}`)
2323
process.exit(1)
2424
}
2525

2626
const YargsPromise = require('yargs-promise')
2727
const updateNotifier = require('update-notifier')
28-
const { print } = require('./utils')
29-
const mfs = require('ipfs-mfs/cli')
3028
const debug = require('debug')('ipfs:cli')
3129
const parser = require('./parser')
3230
const commandAlias = require('./command-alias')
31+
const { print } = require('./utils')
3332

34-
function main (args) {
35-
const oneWeek = 1000 * 60 * 60 * 24 * 7
36-
updateNotifier({ pkg, updateCheckInterval: oneWeek }).notify()
37-
38-
const cli = new YargsPromise(parser)
39-
40-
// add MFS (Files API) commands
41-
mfs(cli)
33+
// Check if an update is available and notify
34+
const oneWeek = 1000 * 60 * 60 * 24 * 7
35+
updateNotifier({ pkg, updateCheckInterval: oneWeek }).notify()
4236

43-
let getIpfs = null
37+
const cli = new YargsPromise(parser)
4438

45-
// Apply command aliasing (eg `refs local` -> `refs-local`)
46-
args = commandAlias(args)
39+
let getIpfs = null
4740

48-
cli
49-
.parse(args)
50-
.then(({ data, argv }) => {
51-
getIpfs = argv.getIpfs
52-
if (data) {
53-
print(data)
54-
}
55-
})
56-
.catch(({ error, argv }) => {
57-
getIpfs = argv && argv.getIpfs
41+
// Apply command aliasing (eg `refs local` -> `refs-local`)
42+
const args = commandAlias(process.argv.slice(2))
43+
cli
44+
.parse(args)
45+
.then(({ data, argv }) => {
46+
getIpfs = argv.getIpfs
47+
if (data) {
48+
print(data)
49+
}
50+
})
51+
.catch(({ error, argv }) => {
52+
getIpfs = argv.getIpfs
53+
if (error.message) {
54+
print(error.message)
5855
debug(error)
59-
// the argument can have a different shape depending on where the error came from
60-
if (error.message || (error.error && error.error.message)) {
61-
print(error.message || error.error.message)
62-
} else {
63-
print('Unknown error, please re-run the command with DEBUG=ipfs:cli to see debug output')
64-
}
65-
process.exit(1)
66-
})
67-
.finally(async () => {
68-
// If an IPFS instance was used in the handler then clean it up here
69-
if (getIpfs && getIpfs.instance) {
70-
try {
71-
const cleanup = getIpfs.rest[0]
72-
await cleanup()
73-
} catch (err) {
74-
debug(err)
75-
process.exit(1)
76-
}
77-
}
78-
})
79-
}
80-
81-
main(process.argv.slice(2))
56+
} else {
57+
print('Unknown error, please re-run the command with DEBUG=ipfs:cli to see debug output')
58+
debug(error)
59+
}
60+
process.exit(1)
61+
})
62+
.finally(() => {
63+
if (getIpfs && getIpfs.instance) {
64+
const cleanup = getIpfs.rest[0]
65+
return cleanup()
66+
}
67+
})

src/cli/commands/id.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ module.exports = {
1616
argv.resolve((async () => {
1717
const ipfs = await argv.getIpfs()
1818
const id = await ipfs.id()
19-
argv.print(JSON.stringify(id, '', 2))
19+
20+
return JSON.stringify(id, '', 2)
2021
})())
2122
}
2223
}

src/cli/parser.js

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

33
const yargs = require('yargs')
4+
const mfs = require('ipfs-mfs/cli')
45
const utils = require('./utils')
56

67
const parser = yargs
@@ -38,4 +39,7 @@ const parser = yargs
3839
.strict()
3940
.completion()
4041

42+
// add MFS (Files API) commands
43+
mfs(parser)
44+
4145
module.exports = parser

src/core/components/files-regular/get-pull-stream.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const exporter = require('ipfs-unixfs-exporter')
44
const toPullStream = require('async-iterator-to-pull-stream')
55
const errCode = require('err-code')
66
const pull = require('pull-stream/pull')
7+
const pullError = require('pull-stream/sources/error')
78
const map = require('pull-stream/throughs/map')
89
const { normalizePath, mapFile } = require('./utils')
910

@@ -17,7 +18,7 @@ module.exports = function (self) {
1718
try {
1819
pathComponents = normalizePath(ipfsPath).split('/')
1920
} catch (err) {
20-
return pull.error(errCode(err, 'ERR_INVALID_PATH'))
21+
return pullError(errCode(err, 'ERR_INVALID_PATH'))
2122
}
2223

2324
self._preload(pathComponents[0])

test/cli/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ describe('config', () => runOnAndOff((thing) => {
5858
})
5959

6060
it('set a config key with invalid json', () => {
61-
return ipfs.fail('config foo {"bar:0} --json')
61+
return ipfs.fail('config foo {"bar:0"} --json')
6262
})
6363

6464
it('get a config key value', () => {

test/cli/id.js

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,43 @@
11
/* eslint-env mocha */
22
'use strict'
33

4-
const expect = require('chai').expect
5-
const runOnAndOff = require('../utils/on-and-off')
4+
const sinon = require('sinon')
5+
const chai = require('chai')
6+
const dirtyChai = require('dirty-chai')
7+
const expect = chai.expect
8+
const YargsPromise = require('yargs-promise')
9+
const clearModule = require('clear-module')
10+
chai.use(dirtyChai)
611

7-
describe('id', () => runOnAndOff((thing) => {
8-
let ipfs
9-
10-
before(function () {
11-
this.timeout(60 * 1000)
12-
ipfs = thing.ipfs
12+
describe('id', () => {
13+
let cli
14+
let cliUtils
15+
beforeEach(() => {
16+
cliUtils = require('../../src/cli/utils')
17+
cli = new YargsPromise(require('../../src/cli/parser'))
18+
})
19+
afterEach(() => {
20+
sinon.restore()
21+
// TODO: the lines below shouldn't be necessary, cli needs refactor to simplify testability
22+
// Force the next require to not use require cache
23+
clearModule('../../src/cli/utils')
24+
clearModule('../../src/cli/parser')
1325
})
1426

15-
it('get the id', function () {
16-
this.timeout(60 * 1000)
27+
it('should output formatted json string', async () => {
28+
const fakeId = sinon.fake.returns(
29+
{ id: 'id', publicKey: 'publicKey' }
30+
)
31+
32+
sinon
33+
.stub(cliUtils, 'getIPFS')
34+
.callsArgWith(1, null, { id: fakeId })
35+
36+
// TODO: the lines below shouldn't be necessary, cli needs refactor to simplify testability
37+
// Force the next require to not use require cache
38+
clearModule('../../src/cli/commands/id.js')
39+
const { data } = await cli.parse('id')
1740

18-
return ipfs('id').then((res) => {
19-
const id = JSON.parse(res)
20-
expect(id).to.have.property('id')
21-
expect(id).to.have.property('publicKey')
22-
expect(id).to.have.property('addresses')
23-
})
41+
expect(data).to.eq('{\n "id": "id",\n "publicKey": "publicKey"\n}')
2442
})
25-
}))
43+
})

0 commit comments

Comments
 (0)