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

feat: jsipfs add --only-hash (#1233) #1266

Merged
merged 4 commits into from
Mar 17, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 9 additions & 3 deletions src/cli/commands/files/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ module.exports = {
type: 'boolean',
default: false
},
'only-hash': {
alias: 'n',
type: 'boolean',
default: false,
describe: 'Only chunk and hash, do not write'
},
'enable-sharding-experiment': {
type: 'boolean',
default: false
Expand Down Expand Up @@ -182,7 +188,8 @@ module.exports = {
strategy: argv.trickle ? 'trickle' : 'balanced',
shardSplitThreshold: argv.enableShardingExperiment ? argv.shardSplitThreshold : Infinity,
'cid-version': argv['cid-version'],
'raw-leaves': argv['raw-leaves']
'raw-leaves': argv['raw-leaves'],
onlyHash: argv['only-hash']
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be 'only-hash'

Copy link
Contributor

@JonKrone JonKrone Mar 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we keep it onlyHash. cid-version and raw-leaves are the outlier here. There are many hyphenated options we convert to camelCase at the entry points of cli/http-api such as the above shardSplittingThreshold and dag --local-resolve, object --input-enc.

I can change raw-leaves and cid-version instead

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JonKrone I like that. Go for it :)

}

// Temporary restriction on raw-leaves:
Expand Down Expand Up @@ -230,8 +237,7 @@ module.exports = {
}
}

const thing = (cb) => cb(null, ipfs.files.addPullStream(options))
thing(next)
next(null, ipfs.files.addPullStream(options))
}
], (err, addStream) => {
if (err) throw err
Expand Down
2 changes: 1 addition & 1 deletion src/core/components/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function prepareFile (self, opts, file, callback) {
opts = opts || {}

waterfall([
(cb) => self.object.get(file.multihash, cb),
(cb) => opts.onlyHash ? cb(null, file) : self.object.get(file.multihash, cb),
(node, cb) => {
let cid = new CID(node.multihash)

Expand Down
6 changes: 4 additions & 2 deletions src/http/api/resources/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ exports.add = {
is: 1,
then: Joi.boolean().valid(false).required(),
otherwise: Joi.boolean().valid(false)
})
}),
'only-hash': Joi.boolean()
})
// TODO: Necessary until validate "recursive", "stream-channels" etc.
.options({ allowUnknown: true })
Expand Down Expand Up @@ -205,7 +206,8 @@ exports.add = {
const options = {
'cid-version': request.query['cid-version'],
'raw-leaves': request.query['raw-leaves'],
progress: request.query['progress'] ? progressHandler : null
progress: request.query.progress ? progressHandler : null,
onlyHash: Boolean(request.query['only-hash'])
}

const aborter = abortable()
Expand Down
3 changes: 2 additions & 1 deletion test/cli/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ describe('config', () => runOnAndOff((thing) => {
})

it('call config with no arguments', () => {
return ipfs.fail('config')
return ipfs('config')
.then(out => expect(out).to.include('bin.js config <key> [value]'))
})
})

Expand Down
30 changes: 30 additions & 0 deletions test/cli/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
'use strict'

const fs = require('fs')
const os = require('os')
const expect = require('chai').expect
const path = require('path')
const compareDir = require('dir-compare').compareSync
Expand Down Expand Up @@ -270,6 +271,35 @@ describe('files', () => runOnAndOff((thing) => {
})
})

it('add --only-hash outputs correct hash', function () {
return ipfs('files add --only-hash src/init-files/init-docs/readme')
.then(out =>
expect(out)
.to.eql('added QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB readme\n')
)
})

it('add --only-hash does not add a file to the datastore', function () {
this.timeout(30 * 1000)
this.slow(10 * 1000)
const content = String(Math.random() + Date.now())
const filepath = path.join(os.tmpdir(), `${content}.txt`)
fs.writeFileSync(filepath, content)

return ipfs(`files add --only-hash ${filepath}`)
.then(out => {
const hash = out.split(' ')[1]

// 'jsipfs object get <hash>' should timeout with the daemon on
// and should fail fast with the daemon off
return Promise.race([
ipfs.fail(`object get ${hash}`),
new Promise((resolve, reject) => setTimeout(resolve, 4000))
])
.then(() => fs.unlinkSync(filepath))
})
})

it('cat', function () {
this.timeout(30 * 1000)

Expand Down
42 changes: 42 additions & 0 deletions test/http-api/files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* eslint-env mocha */
/* eslint max-nested-callbacks: ["error", 8] */
'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
chai.use(dirtyChai)

describe('.files', () => {
let ipfs = null
let ipfsd = null
before(function (done) {
this.timeout(20 * 1000)
df.spawn({ initOptions: { bits: 512 } }, (err, _ipfsd) => {
expect(err).to.not.exist()
ipfsd = _ipfsd
ipfs = ipfsd.api
done()
})
})

after((done) => ipfsd.stop(done))

describe('.add', function () {
it('performs a speculative add, --only-hash', () => {
const content = String(Math.random())

return ipfs.add(Buffer.from(content), { onlyHash: true })
.then(files => {
const getAttempt = ipfs.object.get(files[0].hash)
.then(() => {
throw new Error('Should not find an object for content added with --only-hash')
})

return Promise.race([
getAttempt,
new Promise((resolve, reject) => setTimeout(resolve, 4000))
])
})
})
})
})
19 changes: 16 additions & 3 deletions test/utils/ipfs-exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,28 @@ module.exports = (repoPath, opts) => {
return res
}

/**
* Expect the command passed as @param arguments to fail.
* @return {Promise} Resolves if the command passed as @param arguments fails,
* rejects if it was successful.
*/
ipfs.fail = function ipfsFail () {
let args = Array.from(arguments)
let caught = false
if (args.length === 1) {
args = args[0].split(' ')
}

return exec(args).catch((err) => {
expect(err).to.exist()
})
return exec(args)
.catch(err => {
caught = true
expect(err).to.exist()
})
.then(() => {
if (!caught) {
throw new Error(`jsipfs expected to fail during command: jsipfs ${args.join(' ')}`)
}
})
}

return ipfs
Expand Down