diff --git a/README.md b/README.md
index 35223f525f..e8f6fcb56a 100644
--- a/README.md
+++ b/README.md
@@ -9,9 +9,9 @@
-
+
-
+
diff --git a/package.json b/package.json
index 742c2eb9b9..a32cd13d41 100644
--- a/package.json
+++ b/package.json
@@ -99,7 +99,7 @@
"ipfs-bitswap": "^0.26.0",
"ipfs-block": "~0.8.1",
"ipfs-block-service": "~0.16.0",
- "ipfs-http-client": "^38.0.1",
+ "ipfs-http-client": "^38.1.0",
"ipfs-http-response": "~0.3.1",
"ipfs-mfs": "^0.13.0",
"ipfs-multipart": "^0.2.0",
@@ -124,6 +124,7 @@
"iso-url": "~0.4.6",
"it-pipe": "^1.0.1",
"it-to-stream": "^0.1.1",
+ "jsondiffpatch": "~0.3.11",
"just-safe-set": "^2.1.0",
"kind-of": "^6.0.2",
"ky": "^0.14.0",
@@ -202,7 +203,7 @@
"execa": "^2.0.4",
"form-data": "^2.5.1",
"hat": "0.0.3",
- "interface-ipfs-core": "^0.115.3",
+ "interface-ipfs-core": "^0.117.2",
"ipfs-interop": "~0.1.0",
"ipfsd-ctl": "^0.47.2",
"libp2p-websocket-star": "~0.10.2",
diff --git a/src/cli/commands/config/profile.js b/src/cli/commands/config/profile.js
new file mode 100644
index 0000000000..2b70510fde
--- /dev/null
+++ b/src/cli/commands/config/profile.js
@@ -0,0 +1,15 @@
+'use strict'
+
+module.exports = {
+ command: 'profile ',
+
+ description: 'Interact with config profiles.',
+
+ builder (yargs) {
+ return yargs
+ .commandDir('profile')
+ },
+
+ handler (argv) {
+ }
+}
diff --git a/src/cli/commands/config/profile/apply.js b/src/cli/commands/config/profile/apply.js
new file mode 100644
index 0000000000..8bd11a028f
--- /dev/null
+++ b/src/cli/commands/config/profile/apply.js
@@ -0,0 +1,35 @@
+'use strict'
+
+const JSONDiff = require('jsondiffpatch')
+
+module.exports = {
+ command: 'apply ',
+
+ describe: 'Apply profile to config',
+
+ builder: {
+ 'dry-run': {
+ type: 'boolean',
+ describe: 'print difference between the current config and the config that would be generated.'
+ }
+ },
+
+ handler (argv) {
+ argv.resolve((async () => {
+ const ipfs = await argv.getIpfs()
+ const diff = await ipfs.config.profiles.apply(argv.profile, { dryRun: argv.dryRun })
+ const delta = JSONDiff.diff(diff.original, diff.updated)
+ const res = JSONDiff.formatters.console.format(delta, diff.original)
+
+ if (res) {
+ argv.print(res)
+
+ if (ipfs.send) {
+ argv.print('\nThe IPFS daemon is running in the background, you may need to restart it for changes to take effect.')
+ }
+ } else {
+ argv.print(`IPFS config already contains the settings from the '${argv.profile}' profile`)
+ }
+ })())
+ }
+}
diff --git a/src/cli/commands/config/profile/ls.js b/src/cli/commands/config/profile/ls.js
new file mode 100644
index 0000000000..04bb74e37f
--- /dev/null
+++ b/src/cli/commands/config/profile/ls.js
@@ -0,0 +1,21 @@
+'use strict'
+
+module.exports = {
+ command: 'ls',
+
+ describe: 'List available config profiles',
+
+ builder: {},
+
+ handler (argv) {
+ argv.resolve(
+ (async () => {
+ const ipfs = await argv.getIpfs()
+
+ for (const profile of await ipfs.config.profiles.list()) {
+ argv.print(`${profile.name}:\n ${profile.description}`)
+ }
+ })()
+ )
+ }
+}
diff --git a/src/cli/commands/init.js b/src/cli/commands/init.js
index 0a3c5de095..02fd90c675 100644
--- a/src/cli/commands/init.js
+++ b/src/cli/commands/init.js
@@ -6,12 +6,15 @@ const { ipfsPathHelp } = require('../utils')
module.exports = {
command: 'init [default-config] [options]',
- describe: 'Initialize a local IPFS node',
+ describe: 'Initialize a local IPFS node\n\n' +
+ 'If you are going to run IPFS in a server environment, you may want to ' +
+ 'initialize it using the \'server\' profile.\n\n' +
+ 'For the list of available profiles run `jsipfs config profile ls`',
builder (yargs) {
return yargs
.epilog(ipfsPathHelp)
.positional('default-config', {
- describe: 'Initialize with the given configuration. Path to the config file. Check https://github.com/ipfs/js-ipfs#optionsconfig',
+ describe: 'Node config, this should be a path to a file or JSON and will be merged with the default config. See https://github.com/ipfs/js-ipfs#optionsconfig',
type: 'string'
})
.option('bits', {
@@ -30,6 +33,14 @@ module.exports = {
type: 'string',
describe: 'Pre-generated private key to use for the repo'
})
+ .option('profile', {
+ alias: 'p',
+ type: 'string',
+ describe: 'Apply profile settings to config. Multiple profiles can be separated by \',\'',
+ coerce: (value) => {
+ return (value || '').split(',')
+ }
+ })
},
handler (argv) {
@@ -66,6 +77,7 @@ module.exports = {
bits: argv.bits,
privateKey: argv.privateKey,
emptyRepo: argv.emptyRepo,
+ profiles: argv.profile,
pass: argv.pass,
log: argv.print
})
diff --git a/src/core/components/config.js b/src/core/components/config.js
index 23d31a1d8a..f36e684521 100644
--- a/src/core/components/config.js
+++ b/src/core/components/config.js
@@ -1,11 +1,129 @@
'use strict'
const callbackify = require('callbackify')
+const getDefaultConfig = require('../runtime/config-nodejs.js')
+const log = require('debug')('ipfs:core:config')
module.exports = function config (self) {
return {
get: callbackify.variadic(self._repo.config.get),
set: callbackify(self._repo.config.set),
- replace: callbackify.variadic(self._repo.config.set)
+ replace: callbackify.variadic(self._repo.config.set),
+ profiles: {
+ apply: callbackify.variadic(applyProfile),
+ list: callbackify.variadic(listProfiles)
+ }
+ }
+
+ async function applyProfile (profileName, opts) {
+ opts = opts || {}
+ const { dryRun } = opts
+
+ const profile = profiles[profileName]
+
+ if (!profile) {
+ throw new Error(`No profile with name '${profileName}' exists`)
+ }
+
+ try {
+ const oldCfg = await self.config.get()
+ let newCfg = JSON.parse(JSON.stringify(oldCfg)) // clone
+ newCfg = profile.transform(newCfg)
+
+ if (!dryRun) {
+ await self.config.replace(newCfg)
+ }
+
+ // Scrub private key from output
+ delete oldCfg.Identity.PrivKey
+ delete newCfg.Identity.PrivKey
+
+ return { original: oldCfg, updated: newCfg }
+ } catch (err) {
+ log(err)
+
+ throw new Error(`Could not apply profile '${profileName}' to config: ${err.message}`)
+ }
+ }
+}
+
+async function listProfiles (options) { // eslint-disable-line require-await
+ return Object.keys(profiles).map(name => ({
+ name,
+ description: profiles[name].description
+ }))
+}
+
+const profiles = {
+ server: {
+ description: 'Disables local host discovery - recommended when running IPFS on machines with public IPv4 addresses.',
+ transform: (config) => {
+ config.Discovery.MDNS.Enabled = false
+ config.Discovery.webRTCStar.Enabled = false
+
+ return config
+ }
+ },
+ 'local-discovery': {
+ description: 'Enables local host discovery - inverse of "server" profile.',
+ transform: (config) => {
+ config.Discovery.MDNS.Enabled = true
+ config.Discovery.webRTCStar.Enabled = true
+
+ return config
+ }
+ },
+ lowpower: {
+ description: 'Reduces daemon overhead on the system - recommended for low power systems.',
+ transform: (config) => {
+ config.Swarm = config.Swarm || {}
+ config.Swarm.ConnMgr = config.Swarm.ConnMgr || {}
+ config.Swarm.ConnMgr.LowWater = 20
+ config.Swarm.ConnMgr.HighWater = 40
+
+ return config
+ }
+ },
+ 'default-power': {
+ description: 'Inverse of "lowpower" profile.',
+ transform: (config) => {
+ const defaultConfig = getDefaultConfig()
+
+ config.Swarm = defaultConfig.Swarm
+
+ return config
+ }
+ },
+ test: {
+ description: 'Reduces external interference of IPFS daemon - for running the daemon in test environments.',
+ transform: (config) => {
+ const defaultConfig = getDefaultConfig()
+
+ config.Addresses.API = defaultConfig.Addresses.API ? '/ip4/127.0.0.1/tcp/0' : ''
+ config.Addresses.Gateway = defaultConfig.Addresses.Gateway ? '/ip4/127.0.0.1/tcp/0' : ''
+ config.Addresses.Swarm = defaultConfig.Addresses.Swarm.length ? ['/ip4/127.0.0.1/tcp/0'] : []
+ config.Bootstrap = []
+ config.Discovery.MDNS.Enabled = false
+ config.Discovery.webRTCStar.Enabled = false
+
+ return config
+ }
+ },
+ 'default-networking': {
+ description: 'Restores default network settings - inverse of "test" profile.',
+ transform: (config) => {
+ const defaultConfig = getDefaultConfig()
+
+ config.Addresses.API = defaultConfig.Addresses.API
+ config.Addresses.Gateway = defaultConfig.Addresses.Gateway
+ config.Addresses.Swarm = defaultConfig.Addresses.Swarm
+ config.Bootstrap = defaultConfig.Bootstrap
+ config.Discovery.MDNS.Enabled = defaultConfig.Discovery.MDNS.Enabled
+ config.Discovery.webRTCStar.Enabled = defaultConfig.Discovery.webRTCStar.Enabled
+
+ return config
+ }
}
}
+
+module.exports.profiles = profiles
diff --git a/src/core/components/files-mfs.js b/src/core/components/files-mfs.js
index 77f2eed0ab..9d621ad60a 100644
--- a/src/core/components/files-mfs.js
+++ b/src/core/components/files-mfs.js
@@ -46,7 +46,7 @@ module.exports = (/** @type { import("../index") } */ ipfs) => {
if (paths.length) {
const options = args[args.length - 1]
- if (options.preload !== false) {
+ if (options && options.preload !== false) {
paths.forEach(path => ipfs._preload(path))
}
}
diff --git a/src/core/components/init.js b/src/core/components/init.js
index 03e6caae13..768a8dd24e 100644
--- a/src/core/components/init.js
+++ b/src/core/components/init.js
@@ -16,6 +16,7 @@ const IPNS = require('../ipns')
const OfflineDatastore = require('../ipns/routing/offline-datastore')
const addDefaultAssets = require('./init-assets')
+const { profiles } = require('./config')
function createPeerId (self, opts) {
if (opts.privateKey) {
@@ -55,6 +56,8 @@ async function createRepo (self, opts) {
const config = mergeOptions(defaultConfig(), self._options.config)
+ applyProfile(self, config, opts)
+
// Verify repo does not exist yet
const exists = await self._repo.exists()
self.log('repo exists?', exists)
@@ -128,8 +131,24 @@ async function addRepoAssets (self, privateKey, opts) {
}
}
+// Apply profiles (eg "server,lowpower") to config
+function applyProfile (self, config, opts) {
+ if (opts.profiles) {
+ for (const name of opts.profiles) {
+ const profile = profiles[name]
+
+ if (!profile) {
+ throw new Error(`Could not find profile with name '${name}'`)
+ }
+
+ self.log(`applying profile ${name}`)
+ profile.transform(config)
+ }
+ }
+}
+
module.exports = function init (self) {
- return callbackify(async (opts) => {
+ return callbackify.variadic(async (opts) => {
opts = opts || {}
await createRepo(self, opts)
diff --git a/src/http/api/resources/config.js b/src/http/api/resources/config.js
index 6c6aa3dfca..bd45c00150 100644
--- a/src/http/api/resources/config.js
+++ b/src/http/api/resources/config.js
@@ -7,6 +7,8 @@ const log = debug('ipfs:http-api:config')
log.error = debug('ipfs:http-api:config:error')
const multipart = require('ipfs-multipart')
const Boom = require('@hapi/boom')
+const Joi = require('@hapi/joi')
+const { profiles } = require('../../../core/components/config')
const all = require('async-iterator-all')
exports.getOrSet = {
@@ -163,3 +165,53 @@ exports.replace = {
return h.response()
}
}
+
+exports.profiles = {
+ apply: {
+ validate: {
+ query: Joi.object().keys({
+ 'dry-run': Joi.boolean().default(false)
+ }).unknown()
+ },
+
+ // pre request handler that parses the args and returns `profile` which is assigned to `request.pre.args`
+ parseArgs: function (request, h) {
+ if (!request.query.arg) {
+ throw Boom.badRequest("Argument 'profile' is required")
+ }
+
+ if (!profiles[request.query.arg]) {
+ throw Boom.badRequest("Argument 'profile' is not a valid profile name")
+ }
+
+ return { profile: request.query.arg }
+ },
+
+ handler: async function (request, h) {
+ const { ipfs } = request.server.app
+ const { profile } = request.pre.args
+ const dryRun = request.query['dry-run']
+
+ try {
+ const diff = await ipfs.config.profiles.apply(profile, { dryRun })
+
+ return h.response({ OldCfg: diff.original, NewCfg: diff.updated })
+ } catch (err) {
+ throw Boom.boomify(err, { message: 'Failed to apply profile' })
+ }
+ }
+ },
+ list: {
+ handler: async function (request, h) {
+ const { ipfs } = request.server.app
+ const list = await ipfs.config.profiles.list()
+
+ return h.response(
+ list.map(profile => ({
+ Name: profile.name,
+ Description: profile.description
+ }))
+ )
+ }
+ }
+}
diff --git a/src/http/api/routes/config.js b/src/http/api/routes/config.js
index 5315a043dc..0f3ea9ddcb 100644
--- a/src/http/api/routes/config.js
+++ b/src/http/api/routes/config.js
@@ -31,5 +31,21 @@ module.exports = [
]
},
handler: resources.config.replace.handler
+ },
+ {
+ method: '*',
+ path: '/api/v0/config/profile/apply',
+ options: {
+ pre: [
+ { method: resources.config.profiles.apply.parseArgs, assign: 'args' }
+ ],
+ validate: resources.config.profiles.apply.validate
+ },
+ handler: resources.config.profiles.apply.handler
+ },
+ {
+ method: '*',
+ path: '/api/v0/config/profile/list',
+ handler: resources.config.profiles.list.handler
}
]
diff --git a/test/cli/commands.js b/test/cli/commands.js
index fc186a11ac..23cc091bd2 100644
--- a/test/cli/commands.js
+++ b/test/cli/commands.js
@@ -4,7 +4,7 @@
const { expect } = require('interface-ipfs-core/src/utils/mocha')
const runOnAndOff = require('../utils/on-and-off')
-const commandCount = 95
+const commandCount = 98
describe('commands', () => runOnAndOff((thing) => {
let ipfs
diff --git a/test/cli/config.js b/test/cli/config.js
index a90df0468b..6b7741dcae 100644
--- a/test/cli/config.js
+++ b/test/cli/config.js
@@ -5,6 +5,8 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha')
const fs = require('fs')
const path = require('path')
const runOnAndOff = require('../utils/on-and-off')
+const defaultConfig = require('../../src/core/runtime/config-nodejs')()
+const { profiles } = require('../../src/core/components/config')
describe('config', () => runOnAndOff((thing) => {
let ipfs
@@ -86,4 +88,51 @@ describe('config', () => runOnAndOff((thing) => {
restoreConfig()
})
})
+
+ describe('profile', function () {
+ this.timeout(40 * 1000)
+
+ let originalConfig
+
+ beforeEach(() => {
+ restoreConfig()
+ originalConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'))
+ })
+
+ after(() => {
+ restoreConfig()
+ })
+
+ Object.keys(profiles).forEach(profile => {
+ it(`applies profile '${profile}'`, async () => {
+ await ipfs(`config profile apply ${profile}`)
+
+ expect(updatedConfig()).to.deep.equal(profiles[profile].transform(originalConfig))
+ })
+ })
+
+ it('--dry-run causes no change', async () => {
+ await ipfs('config profile apply --dry-run=true server')
+ const after = updatedConfig()
+ expect(after.Discovery.MDNS.Enabled).to.equal(defaultConfig.Discovery.MDNS.Enabled)
+
+ await ipfs('config profile apply --dry-run=false server')
+ const updated = updatedConfig()
+ expect(updated.Discovery.MDNS.Enabled).to.equal(false)
+ })
+
+ it('Private key does not appear in output', async () => {
+ const out = await ipfs('config profile apply server')
+ expect(out).not.includes('PrivKey')
+ })
+
+ it('lists available config profiles', async () => {
+ const out = await ipfs('config profile ls')
+
+ Object.keys(profiles => profile => {
+ expect(out).includes(profiles[profile].name)
+ expect(out).includes(profiles[profile].description)
+ })
+ })
+ })
}))
diff --git a/test/cli/init.js b/test/cli/init.js
index 234d5b4c39..97bb486fbc 100644
--- a/test/cli/init.js
+++ b/test/cli/init.js
@@ -26,6 +26,11 @@ describe('init', function () {
return !f.startsWith('.')
})
}
+
+ const repoConfSync = (p) => {
+ return JSON.parse(fs.readFileSync(path.join(repoPath, 'config')))
+ }
+
beforeEach(() => {
repoPath = os.tmpdir() + '/ipfs-' + hat()
ipfs = ipfsExec(repoPath)
@@ -60,6 +65,37 @@ describe('init', function () {
expect(repoExistsSync('version')).to.equal(true)
})
+ it('profile', async function () {
+ this.timeout(40 * 1000)
+
+ await ipfs('init --profile lowpower')
+ expect(repoConfSync().Swarm.ConnMgr.LowWater).to.equal(20)
+ })
+
+ it('profile multiple', async function () {
+ this.timeout(40 * 1000)
+
+ await ipfs('init --profile server,lowpower')
+ expect(repoConfSync().Discovery.MDNS.Enabled).to.equal(false)
+ expect(repoConfSync().Swarm.ConnMgr.LowWater).to.equal(20)
+ })
+
+ it('profile non-existent', async function () {
+ this.timeout(40 * 1000)
+
+ try {
+ await ipfs('init --profile doesnt-exist')
+ } catch (err) {
+ expect(err.stdout).includes('Could not find profile')
+ }
+ })
+
+ it('should present ipfs path help when option help is received', async function () {
+ const res = await ipfs('init --help')
+
+ expect(res).to.have.string('export IPFS_PATH=/path/to/ipfsrepo')
+ })
+
it('should present ipfs path help when option help is received', async function () {
const res = await ipfs('init --help')
expect(res).to.have.string('export IPFS_PATH=/path/to/ipfsrepo')
diff --git a/test/core/interface.spec.js b/test/core/interface.spec.js
index 84a386e353..5ac674782c 100644
--- a/test/core/interface.spec.js
+++ b/test/core/interface.spec.js
@@ -12,26 +12,16 @@ describe('interface-ipfs-core tests', function () {
tests.bitswap(defaultCommonFactory, { skip: !isNode })
- tests.block(defaultCommonFactory)
+ tests.block(defaultCommonFactory, {
+ skip: [{
+ name: 'rm',
+ reason: 'Not implemented'
+ }]
+ })
tests.bootstrap(defaultCommonFactory)
- tests.config(defaultCommonFactory, {
- skip: [
- {
- name: 'should set a number',
- reason: 'Failing - needs to be fixed'
- },
- {
- name: 'should output changes but not save them for dry run',
- reason: 'TODO unskip when https://github.com/ipfs/js-ipfs/pull/2165 is merged'
- },
- {
- name: 'should set a config profile',
- reason: 'TODO unskip when https://github.com/ipfs/js-ipfs/pull/2165 is merged'
- }
- ]
- })
+ tests.config(defaultCommonFactory)
tests.dag(defaultCommonFactory)
diff --git a/test/core/name.spec.js b/test/core/name.spec.js
index d517707c9e..f1da264e9d 100644
--- a/test/core/name.spec.js
+++ b/test/core/name.spec.js
@@ -5,10 +5,8 @@
const hat = require('hat')
const { expect } = require('interface-ipfs-core/src/utils/mocha')
const sinon = require('sinon')
-
const parallel = require('async/parallel')
const series = require('async/series')
-
const IPFS = require('../../src')
const ipnsPath = require('../../src/core/ipns/path')
const ipnsRouting = require('../../src/core/ipns/routing/config')
diff --git a/test/core/pin.js b/test/core/pin.js
index d5e096ad3a..124a5a8acc 100644
--- a/test/core/pin.js
+++ b/test/core/pin.js
@@ -4,7 +4,6 @@
const { expect } = require('interface-ipfs-core/src/utils/mocha')
const fs = require('fs')
-
const {
DAGNode
} = require('ipld-dag-pb')
diff --git a/test/http-api/inject/config.js b/test/http-api/inject/config.js
index 852a65a0d9..53eb9f8785 100644
--- a/test/http-api/inject/config.js
+++ b/test/http-api/inject/config.js
@@ -6,6 +6,7 @@ const fs = require('fs')
const FormData = require('form-data')
const streamToPromise = require('stream-to-promise')
const path = require('path')
+const { profiles } = require('../../../src/core/components/config')
module.exports = (http) => {
describe('/config', () => {
@@ -189,5 +190,73 @@ module.exports = (http) => {
expect(updatedConfig()).to.deep.equal(expectedConfig)
})
})
+
+ describe('/config/profile/apply', () => {
+ let originalConfig
+
+ beforeEach(() => {
+ originalConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'))
+ })
+
+ it('returns 400 if no config profile is provided', async () => {
+ const res = await api.inject({
+ method: 'POST',
+ url: '/api/v0/config/profile/apply'
+ })
+
+ expect(res.statusCode).to.equal(400)
+ })
+
+ it('returns 400 if the config profile is invalid', async () => {
+ const res = await api.inject({
+ method: 'POST',
+ url: '/api/v0/config/profile/apply?arg=derp'
+ })
+
+ expect(res.statusCode).to.equal(400)
+ })
+
+ it('does not apply config profile with dry-run argument', async () => {
+ const res = await api.inject({
+ method: 'POST',
+ url: '/api/v0/config/profile/apply?arg=lowpower&dry-run=true'
+ })
+
+ expect(res.statusCode).to.equal(200)
+ expect(updatedConfig()).to.deep.equal(originalConfig)
+ })
+
+ Object.keys(profiles).forEach(profile => {
+ it(`applies config profile ${profile}`, async () => {
+ const res = await api.inject({
+ method: 'POST',
+ url: `/api/v0/config/profile/apply?arg=${profile}`
+ })
+
+ expect(res.statusCode).to.equal(200)
+ expect(updatedConfig()).to.deep.equal(profiles[profile].transform(originalConfig))
+ })
+ })
+ })
+
+ describe('/config/profile/list', () => {
+ it('lists available profiles', async () => {
+ const res = await api.inject({
+ method: 'POST',
+ url: '/api/v0/config/profile/list'
+ })
+
+ expect(res.statusCode).to.equal(200)
+
+ const listed = JSON.parse(res.payload)
+
+ Object.keys(profiles).forEach(name => {
+ const profile = listed.find(profile => profile.Name === name)
+
+ expect(profile).to.be.ok()
+ expect(profile.Description).to.equal(profiles[name].description)
+ })
+ })
+ })
})
}
diff --git a/test/http-api/inject/name.js b/test/http-api/inject/name.js
index 2fbf56c499..3fe7f2564c 100644
--- a/test/http-api/inject/name.js
+++ b/test/http-api/inject/name.js
@@ -3,7 +3,6 @@
'use strict'
const { expect } = require('interface-ipfs-core/src/utils/mocha')
-
const checkAll = (bits) => string => bits.every(bit => string.includes(bit))
module.exports = (http) => {
diff --git a/test/http-api/interface.js b/test/http-api/interface.js
index 3373f36069..7469be1564 100644
--- a/test/http-api/interface.js
+++ b/test/http-api/interface.js
@@ -12,26 +12,16 @@ describe('interface-ipfs-core over ipfs-http-client tests', () => {
tests.bitswap(defaultCommonFactory)
- tests.block(defaultCommonFactory)
+ tests.block(defaultCommonFactory, {
+ skip: [{
+ name: 'rm',
+ reason: 'Not implemented'
+ }]
+ })
tests.bootstrap(defaultCommonFactory)
- tests.config(defaultCommonFactory, {
- skip: [
- {
- name: 'should set a number',
- reason: 'Failing - needs to be fixed'
- },
- {
- name: 'should output changes but not save them for dry run',
- reason: 'TODO unskip when https://github.com/ipfs/js-ipfs/pull/2165 is merged'
- },
- {
- name: 'should set a config profile',
- reason: 'TODO unskip when https://github.com/ipfs/js-ipfs/pull/2165 is merged'
- }
- ]
- })
+ tests.config(defaultCommonFactory)
tests.dag(defaultCommonFactory, {
skip: [{