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

Commit 4406bb7

Browse files
committed
feat: add mfs implementation
1 parent 45b705d commit 4406bb7

File tree

23 files changed

+481
-84
lines changed

23 files changed

+481
-84
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ Creates and returns an instance of an IPFS node. Use the `options` argument to s
233233
- `hop` (object)
234234
- `enabled` (boolean): Make this node a relay (other nodes can connect *through* it). (Default: `false`)
235235
- `active` (boolean): Make this an *active* relay node. Active relay nodes will attempt to dial a destination peer even if that peer is not yet connected to the relay. (Default: `false`)
236-
236+
237237
- `config` (object) Modify the default IPFS node config. Find the Node.js defaults at [`src/core/runtime/config-nodejs.js`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/config-nodejs.js) and the browser defaults at [`src/core/runtime/config-browser.js`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/config-browser.js). This object will be *merged* with the default config; it will not replace it.
238238

239239
- `libp2p` (object) add custom modules to the libp2p stack of your node

examples/circuit-relaying/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"ipfs-pubsub-room": "~0.3.0"
1919
},
2020
"devDependencies": {
21-
"aegir": "^13.0.5",
21+
"aegir": "^14.0.0",
2222
"http-server": "~0.10.0",
2323
"ipfs-css": "~0.2.0",
2424
"parcel-bundler": "^1.6.2",

package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,12 @@
6161
},
6262
"homepage": "https://github.com/ipfs/js-ipfs#readme",
6363
"devDependencies": {
64-
"aegir": "^13.1.0",
64+
"aegir": "^14.0.0",
6565
"buffer-loader": "~0.0.1",
6666
"chai": "^4.1.2",
6767
"delay": "^2.0.0",
6868
"detect-node": "^2.0.3",
69+
"detect-webworker": "^1.0.0",
6970
"dir-compare": "^1.4.0",
7071
"dirty-chai": "^2.0.1",
7172
"eslint-plugin-react": "^7.7.0",
@@ -111,7 +112,8 @@
111112
"ipfs-bitswap": "~0.20.0",
112113
"ipfs-block": "~0.7.1",
113114
"ipfs-block-service": "~0.14.0",
114-
"ipfs-http-response": "^0.1.2",
115+
"ipfs-http-response": "~0.1.2",
116+
"ipfs-mfs": "~0.0.4",
115117
"ipfs-multipart": "~0.1.0",
116118
"ipfs-repo": "~0.22.1",
117119
"ipfs-unixfs": "~0.1.15",
@@ -175,7 +177,8 @@
175177
"through2": "^2.0.3",
176178
"update-notifier": "^2.5.0",
177179
"yargs": "^11.0.0",
178-
"yargs-parser": "^10.0.0"
180+
"yargs-parser": "^10.0.0",
181+
"yargs-promise": "^1.1.0"
179182
},
180183
"optionalDependencies": {
181184
"prom-client": "^11.0.0",

src/cli/bin.js

+46-34
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
'use strict'
44

5+
const YargsPromise = require('yargs-promise')
56
const yargs = require('yargs')
67
const updateNotifier = require('update-notifier')
78
const readPkgUp = require('read-pkg-up')
8-
const fs = require('fs')
9-
const path = require('path')
109
const utils = require('./utils')
1110
const print = utils.print
11+
const mfs = require('ipfs-mfs/cli')
12+
const debug = require('debug')('ipfs:cli')
1213

1314
const pkg = readPkgUp.sync({cwd: __dirname}).pkg
1415
updateNotifier({
@@ -18,10 +19,6 @@ updateNotifier({
1819

1920
const args = process.argv.slice(2)
2021

21-
// Determine if the first argument is a sub-system command
22-
const commandNames = fs.readdirSync(path.join(__dirname, 'commands'))
23-
const isCommand = commandNames.includes(`${args[0]}.js`)
24-
2522
const cli = yargs
2623
.option('silent', {
2724
desc: 'Write no output',
@@ -34,14 +31,6 @@ const cli = yargs
3431
type: 'string',
3532
default: ''
3633
})
37-
.commandDir('commands', {
38-
// Only include the commands for the sub-system we're using, or include all
39-
// if no sub-system command has been passed.
40-
include (path, filename) {
41-
if (!isCommand) return true
42-
return `${args[0]}.js` === filename
43-
}
44-
})
4534
.epilog(utils.ipfsPathHelp)
4635
.demandCommand(1)
4736
.fail((msg, err, yargs) => {
@@ -56,27 +45,15 @@ const cli = yargs
5645
yargs.showHelp()
5746
})
5847

59-
// If not a sub-system command then load the top level aliases
60-
if (!isCommand) {
61-
// NOTE: This creates an alias of
62-
// `jsipfs files {add, get, cat}` to `jsipfs {add, get, cat}`.
63-
// This will stay until https://github.com/ipfs/specs/issues/98 is resolved.
64-
const addCmd = require('./commands/files/add')
65-
const catCmd = require('./commands/files/cat')
66-
const getCmd = require('./commands/files/get')
67-
const aliases = [addCmd, catCmd, getCmd]
68-
aliases.forEach((alias) => {
69-
cli.command(alias.command, alias.describe, alias.builder, alias.handler)
70-
})
71-
}
72-
7348
// Need to skip to avoid locking as these commands
7449
// don't require a daemon
7550
if (args[0] === 'daemon' || args[0] === 'init') {
7651
cli
7752
.help()
7853
.strict()
7954
.completion()
55+
.command(require('./commands/daemon'))
56+
.command(require('./commands/init'))
8057
.parse(args)
8158
} else {
8259
// here we have to make a separate yargs instance with
@@ -86,19 +63,54 @@ if (args[0] === 'daemon' || args[0] === 'init') {
8663
if (err) {
8764
throw err
8865
}
66+
8967
utils.getIPFS(argv, (err, ipfs, cleanup) => {
90-
if (err) { throw err }
68+
if (err) {
69+
throw err
70+
}
71+
72+
// add mfs commands
73+
mfs(cli)
74+
75+
// NOTE: This creates an alias of
76+
// `jsipfs files {add, get, cat}` to `jsipfs {add, get, cat}`.
77+
// This will stay until https://github.com/ipfs/specs/issues/98 is resolved.
78+
const addCmd = require('./commands/files/add')
79+
const catCmd = require('./commands/files/cat')
80+
const getCmd = require('./commands/files/get')
81+
const aliases = [addCmd, catCmd, getCmd]
82+
aliases.forEach((alias) => {
83+
cli.command(alias)
84+
})
9185

9286
cli
87+
.commandDir('commands')
9388
.help()
9489
.strict()
9590
.completion()
96-
.parse(args, { ipfs: ipfs }, (err, argv, output) => {
97-
if (output) { print(output) }
9891

99-
cleanup(() => {
100-
if (err) { throw err }
101-
})
92+
const parser = new YargsPromise(cli, { ipfs })
93+
parser.parse(args)
94+
.then(({ data, argv }) => {
95+
if (data) {
96+
print(data)
97+
}
98+
99+
return cleanup()
100+
})
101+
.catch((arg) => {
102+
debug(arg)
103+
104+
// the argument can have a different shape depending on where the error came from
105+
if (arg.message) {
106+
print(arg.message)
107+
} else if (arg.error && arg.error.message) {
108+
print(arg.error.message)
109+
} else {
110+
print('Unknown error, please re-run the command with DEBUG=ipfs:cli to see debug output')
111+
}
112+
113+
process.exit(1)
102114
})
103115
})
104116
})

src/cli/commands/dag/get.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ module.exports = {
4141
// * reads as 'agree in'
4242
if (node._json) {
4343
delete node._json.multihash
44-
node._json.data = '0x' + node._json.data.toString('hex')
44+
node._json.data = node._json.data.toString('base64')
4545
print(JSON.stringify(node._json))
4646
return
4747
}

src/cli/commands/files.js

-20
This file was deleted.

src/cli/commands/files/get.js

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ function fileHandler (dir) {
3030
callback(err)
3131
} else {
3232
const fullFilePath = path.join(dir, file.path)
33+
3334
if (file.content) {
3435
file.content
3536
.pipe(fs.createWriteStream(fullFilePath))

src/cli/utils.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const log = debug('cli')
99
log.error = debug('cli:error')
1010
const Progress = require('progress')
1111
const byteman = require('byteman')
12+
const promisify = require('promisify-es6')
1213

1314
exports = module.exports
1415

@@ -40,7 +41,7 @@ function getAPICtl (apiAddr) {
4041

4142
exports.getIPFS = (argv, callback) => {
4243
if (argv.api || isDaemonOn()) {
43-
return callback(null, getAPICtl(argv.api), (cb) => cb())
44+
return callback(null, getAPICtl(argv.api), promisify((cb) => cb()))
4445
}
4546

4647
// Required inline to reduce startup time
@@ -55,13 +56,13 @@ exports.getIPFS = (argv, callback) => {
5556
}
5657
})
5758

58-
const cleanup = (cb) => {
59+
const cleanup = promisify((cb) => {
5960
if (node && node._repo && !node._repo.closed) {
60-
node._repo.close(() => cb())
61+
node._repo.close((err) => cb(err))
6162
} else {
6263
cb()
6364
}
64-
}
65+
})
6566

6667
node.on('error', (err) => {
6768
throw err

src/core/components/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ exports.dht = require('./dht')
2626
exports.dns = require('./dns')
2727
exports.key = require('./key')
2828
exports.stats = require('./stats')
29+
exports.mfs = require('ipfs-mfs/core')

src/core/config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const schema = Joi.object().keys({
1616
EXPERIMENTAL: Joi.object().keys({
1717
pubsub: Joi.boolean(),
1818
sharding: Joi.boolean(),
19-
dht: Joi.boolean()
19+
dht: Joi.boolean(),
20+
mfs: Joi.boolean()
2021
}).allow(null),
2122
config: Joi.object().keys({
2223
Addresses: Joi.object().keys({

src/core/index.js

+9
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,15 @@ class IPFS extends EventEmitter {
137137
isIPFS: isIPFS
138138
}
139139

140+
// ipfs.files
141+
const mfs = components.mfs(this)
142+
143+
Object.keys(mfs).forEach(key => {
144+
if (mfs.hasOwnProperty(key)) {
145+
this.files[key] = mfs[key]
146+
}
147+
})
148+
140149
boot(this)
141150
}
142151
}

src/http/api/routes/files.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22

33
const resources = require('./../resources')
4+
const mfs = require('ipfs-mfs/http')
45

56
module.exports = (server) => {
67
const api = server.select('API')
@@ -54,4 +55,6 @@ module.exports = (server) => {
5455
handler: resources.files.immutableLs.handler
5556
}
5657
})
58+
59+
mfs(api)
5760
}

test/browser.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict'
2+
3+
const isWebWorker = require('detect-webworker')
4+
5+
if (isWebWorker) {
6+
// https://github.com/Joris-van-der-Wel/karma-mocha-webworker/issues/4
7+
global.MFS_DISABLE_CONCURRENCY = true
8+
}

test/cli/commands.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
const expect = require('chai').expect
55
const runOnAndOff = require('../utils/on-and-off')
66

7-
const commandCount = 78
7+
const commandCount = 77
8+
89
describe('commands', () => runOnAndOff((thing) => {
910
let ipfs
1011

test/cli/file.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe('file ls', () => runOnAndOff((thing) => {
1212
before(function () {
1313
this.timeout(50 * 1000)
1414
ipfs = thing.ipfs
15-
return ipfs('files add -r test/fixtures/test-data/recursive-get-dir')
15+
return ipfs('add -r test/fixtures/test-data/recursive-get-dir')
1616
})
1717

1818
it('prints a filename', () => {

0 commit comments

Comments
 (0)