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

[WIP] feat: CID base option for ipfs.add #1441

Closed
wants to merge 10 commits into from
2 changes: 1 addition & 1 deletion src/cli/commands/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module.exports = {
httpAPI = new HttpAPI(process.env.IPFS_PATH, null, argv)

httpAPI.start((err) => {
if (err && err.code === 'ENOENT' && err.message.match(/Uninitalized repo/i)) {
if (err && err.code === 'ENOENT' && err.message.match(/uninitialized/i)) {
print('Error: no initialized ipfs repo found in ' + repoPath)
print('please run: jsipfs init')
process.exit(1)
Expand Down
9 changes: 9 additions & 0 deletions src/cli/commands/files/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ module.exports = {
type: 'integer',
describe: 'Cid version. Non-zero value will change default of \'raw-leaves\' to true. (experimental)'
},
'cid-base': {
type: 'string',
describe: 'The multibase of the printed CID for added files. (experimental)'
},
hash: {
type: 'string',
choices: Object.keys(mh.names),
Expand Down Expand Up @@ -190,6 +194,7 @@ module.exports = {
? argv.shardSplitThreshold
: Infinity,
cidVersion: argv.cidVersion,
cidBase: argv.cidBase,
rawLeaves: argv.rawLeaves,
onlyHash: argv.onlyHash,
hashAlg: argv.hash,
Expand All @@ -209,6 +214,10 @@ module.exports = {
throw new Error('Implied argument raw-leaves must be passed and set to false when cid-version is > 0')
}

if (options.cidBase && options.cidVersion !== 1) {
options.cidVersion = 1
}

// Temporary restriction on raw-leaves:
// When hash != undefined then raw-leaves MUST be present and false.
//
Expand Down
151 changes: 59 additions & 92 deletions src/core/boot.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
'use strict'

const waterfall = require('async/waterfall')
const series = require('async/series')
const extend = require('deep-extend')
const RepoErrors = require('ipfs-repo').errors

// Boot an IPFS node depending on the options set
Expand All @@ -11,110 +9,79 @@ module.exports = (self) => {
const options = self._options
const doInit = options.init
const doStart = options.start
const config = options.config
const setConfig = config && typeof config === 'object'
const repoOpen = !self._repo.closed

const customInitOptions = typeof options.init === 'object' ? options.init : {}
const initOptions = Object.assign({ bits: 2048, pass: self._options.pass }, customInitOptions)

// Checks if a repo exists, and if so opens it
// Will return callback with a bool indicating the existence
// of the repo
const maybeOpenRepo = (cb) => {
// nothing to do
if (repoOpen) {
return cb(null, true)
}
// Do the actual boot sequence
waterfall([
// Checks if a repo exists, and if so opens it
// Will return callback with a bool indicating the existence
// of the repo
(cb) => {
// nothing to do
if (!self._repo.closed) {
return cb(null, true)
}

series([
(cb) => self._repo.open(cb),
(cb) => self.pin._load(cb),
(cb) => self.preStart(cb),
(cb) => {
self.log('initialized')
self.state.initialized()
self._repo.open((err, res) => {
if (isRepoUninitializedError(err)) return cb(null, false)
if (err) return cb(err)
cb(null, true)
})
},
(repoOpened, cb) => {
// Init with existing initialized, opened, repo
if (repoOpened) {
return self.init({ repo: self._repo }, (err) => cb(err))
}
], (err, res) => {
if (err) {
// If the error is that no repo exists,
// which happens when the version file is not found
// we just want to signal that no repo exist, not
// fail the whole process.

// Use standardized errors as much as possible
if (err.code === RepoErrors.ERR_REPO_NOT_INITIALIZED) {
return cb(null, false)
}

// TODO: As error codes continue to be standardized, this logic can be phase out;
// it is here to maintain compatability
if (err.message.match(/not found/) || // indexeddb
err.message.match(/ENOENT/) || // fs
err.message.match(/No value/) // memory
) {
return cb(null, false)
}
return cb(err)
if (doInit) {
const initOptions = Object.assign(
{ bits: 2048, pass: self._options.pass },
typeof options.init === 'object' ? options.init : {}
)
return self.init(initOptions, (err) => cb(err))
}
cb(null, res)
})
}

const done = (err) => {
cb()
},
(cb) => {
// No problem, we don't have to start the node
if (!doStart) {
return cb()
}
self.start(cb)
}
], (err) => {
if (err) {
return self.emit('error', err)
}
self.log('boot:done')
self.log('booted')
self.emit('ready')
}

const tasks = []

// check if there as a repo and if so open it
maybeOpenRepo((err, hasRepo) => {
if (err) {
return done(err)
}
})
}

// No repo, but need should init one
if (doInit && !hasRepo) {
tasks.push((cb) => self.init(initOptions, cb))
// we know we will have a repo for all follwing tasks
// if the above succeeds
hasRepo = true
}
function isRepoUninitializedError (err) {
if (!err) {
return false
}

// Need to set config
if (setConfig) {
if (!hasRepo) {
console.log('WARNING, trying to set config on uninitialized repo, maybe forgot to set "init: true"')
} else {
tasks.push((cb) => {
waterfall([
(cb) => self.config.get(cb),
(config, cb) => {
extend(config, options.config)
// If the error is that no repo exists,
// which happens when the version file is not found
// we just want to signal that no repo exist, not
// fail the whole process.

self.config.replace(config, cb)
}
], cb)
})
}
}
// Use standardized errors as much as possible
if (err.code === RepoErrors.ERR_REPO_NOT_INITIALIZED) {
return true
}

// Need to start up the node
if (doStart) {
if (!hasRepo) {
console.log('WARNING, trying to start ipfs node on uninitialized repo, maybe forgot to set "init: true"')
return done(new Error('Uninitalized repo'))
} else {
tasks.push((cb) => self.start(cb))
}
}
// TODO: As error codes continue to be standardized, this logic can be phase out;
// it is here to maintain compatability
if (err.message.match(/not found/) || // indexeddb
err.message.match(/ENOENT/) || // fs
err.message.match(/No value/) // memory
) {
return true
}

// Do the actual boot sequence
series(tasks, done)
})
return false
}
16 changes: 13 additions & 3 deletions src/core/components/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ function prepareFile (self, opts, file, callback) {
? cb(null, file)
: self.object.get(file.multihash, opts, cb),
(node, cb) => {
const b58Hash = cid.toBaseEncodedString()
const hash = cid.toBaseEncodedString(opts.cidBase)

cb(null, {
path: opts.wrapWithDirectory ? file.path.substring(WRAPPER.length) : (file.path || b58Hash),
hash: b58Hash,
path: opts.wrapWithDirectory
? file.path.substring(WRAPPER.length)
: (file.path || hash),
hash: hash,
size: node.size
})
}
Expand Down Expand Up @@ -144,6 +146,10 @@ module.exports = function files (self) {
opts.cidVersion = 1
}

if (opts.cidBase && opts.cidVersion !== 1) {
opts.cidVersion = 1
}

let total = 0

const prog = opts.progress || noop
Expand Down Expand Up @@ -246,6 +252,10 @@ module.exports = function files (self) {
options.cidVersion = 1
}

if (options.cidBase && options.cidVersion !== 1) {
options.cidVersion = 1
}

pull(
pull.values([data]),
_addPullStream(options),
Expand Down
21 changes: 17 additions & 4 deletions src/core/components/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,31 @@ module.exports = function init (self) {
return callback(err)
}

self.state.initialized()
self.emit('init')
callback(null, res)
self.preStart((err) => {
if (err) {
self.emit('error', err)
return callback(err)
}

self.state.initialized()
self.emit('init')
callback(null, res)
})
}

if (self.state.state() !== 'uninitalized') {
if (self.state.state() !== 'uninitialized') {
return done(new Error('Not able to init from state: ' + self.state.state()))
}

self.state.init()
self.log('init')

// An initialized, open repo was passed, use this one!
if (opts.repo) {
self._repo = opts.repo
return done(null, true)
}

opts.emptyRepo = opts.emptyRepo || false
opts.bits = Number(opts.bits) || 2048
opts.log = opts.log || function () {}
Expand Down
19 changes: 18 additions & 1 deletion src/core/components/pre-start.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const PeerInfo = require('peer-info')
const multiaddr = require('multiaddr')
const waterfall = require('async/waterfall')
const Keychain = require('libp2p-keychain')
const extend = require('deep-extend')
const NoKeychain = require('./no-keychain')
/*
* Load stuff from Repo into memory
Expand All @@ -16,6 +17,21 @@ module.exports = function preStart (self) {
const pass = self._options.pass
waterfall([
(cb) => self._repo.config.get(cb),
(config, cb) => {
if (!self._options.config) {
return cb(null, config)
}

extend(config, self._options.config)

self.config.replace(config, (err) => {
if (err) {
return cb(err)
}

cb(null, config)
})
},
(config, cb) => {
// Create keychain configuration, if needed.
if (config.Keychain) {
Expand Down Expand Up @@ -78,7 +94,8 @@ module.exports = function preStart (self) {
}

cb()
}
},
(cb) => self.pin._load(cb)
], callback)
}
}
33 changes: 15 additions & 18 deletions src/core/components/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ const promisify = require('promisify-es6')

module.exports = (self) => {
return promisify((callback) => {
callback = callback || function noop () {}

const done = (err) => {
if (err) {
setImmediate(() => self.emit('error', err))
Expand All @@ -21,32 +19,31 @@ module.exports = (self) => {
}

if (self.state.state() !== 'stopped') {
return done(new Error('Not able to start from state: ' + self.state.state()))
return done(new Error(`Not able to start from state: ${self.state.state()}`))
}

self.log('starting')
self.state.start()

series([
(cb) => {
// The repo may be closed if previously stopped
self._repo.closed
? self._repo.open(cb)
: cb()
},
(cb) => self.preStart(cb),
(cb) => self.libp2p.start(cb)
], (err) => {
if (err) { return done(err) }

self._bitswap = new Bitswap(
self._libp2pNode,
self._repo.blocks,
{ statsEnabled: true }
)

self._bitswap.start()
self._blockService.setExchange(self._bitswap)
done()
})
(cb) => self.libp2p.start(cb),
(cb) => {
self._bitswap = new Bitswap(
self._libp2pNode,
self._repo.blocks,
{ statsEnabled: true }
)

self._bitswap.start()
self._blockService.setExchange(self._bitswap)
cb()
}
], done)
})
}
Loading