Skip to content
This repository was 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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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