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

feat: add mssing dag put and dag resolve cli commands #2521

Merged
merged 4 commits into from
Oct 19, 2019
Merged
Show file tree
Hide file tree
Changes from 3 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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@
"form-data": "^2.5.1",
"hat": "0.0.3",
"interface-ipfs-core": "^0.117.2",
"ipfs-interop": "~0.1.0",
"ipfs-interop": "^0.1.1",
"ipfsd-ctl": "^0.47.2",
"libp2p-websocket-star": "~0.10.2",
"ncp": "^2.0.0",
Expand Down
124 changes: 124 additions & 0 deletions src/cli/commands/dag/put.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
'use strict'

const mh = require('multihashes')
const multibase = require('multibase')
const dagCBOR = require('ipld-dag-cbor')
const dagPB = require('ipld-dag-pb')
const { cidToString } = require('../../../utils/cid')

const inputDecoders = {
json: (buf) => JSON.parse(buf.toString()),
cbor: (buf) => dagCBOR.util.deserialize(buf),
protobuf: (buf) => dagPB.util.deserialize(buf),
raw: (buf) => buf
}

const formats = {
cbor: 'dag-cbor',
raw: 'raw',
protobuf: 'dag-pb',
'dag-cbor': 'dag-cbor',
'dag-pb': 'dag-pb'
}

module.exports = {
command: 'put [data]',

describe: 'accepts input from a file or stdin and parses it into an object of the specified format',

builder: {
data: {
type: 'string'
},
format: {
type: 'string',
alias: 'f',
default: 'cbor',
describe: 'Format that the object will be added as',
choices: ['dag-cbor', 'dag-pb', 'raw', 'cbor', 'protobuf']
},
'input-encoding': {
type: 'string',
alias: 'input-enc',
default: 'json',
describe: 'Format that the input object will be',
choices: ['json', 'cbor', 'raw', 'protobuf']
},
pin: {
type: 'boolean',
default: true,
describe: 'Pin this object when adding'
},
'hash-alg': {
type: 'string',
alias: 'hash',
default: 'sha2-256',
describe: 'Hash function to use',
choices: Object.keys(mh.names)
},
'cid-version': {
type: 'integer',
describe: 'CID version. Defaults to 0 unless an option that depends on CIDv1 is passed',
default: 0
},
'cid-base': {
describe: 'Number base to display CIDs in.',
type: 'string',
choices: multibase.names
},
preload: {
type: 'boolean',
default: true,
describe: 'Preload this object when adding'
},
'only-hash': {
type: 'boolean',
default: false,
describe: 'Only hash the content, do not write to the underlying block store'
}
},

handler ({ data, format, inputEncoding, pin, hashAlg, cidVersion, cidBase, preload, onlyHash, getIpfs, print, resolve }) {
resolve((async () => {
const ipfs = await getIpfs()

if (inputEncoding === 'cbor') {
format = 'dag-cbor'
} else if (inputEncoding === 'protobuf') {
format = 'dag-pb'
}

format = formats[format]

if (format !== 'dag-pb') {
cidVersion = 1
}

let source = data

if (!source) {
// pipe from stdin
source = Buffer.alloc(0)

for await (const buf of process.stdin) {
source = Buffer.concat([source, buf])
}
} else {
source = Buffer.from(source)
}

source = inputDecoders[inputEncoding](source)

const cid = await ipfs.dag.put(source, {
format,
hashAlg,
version: cidVersion,
onlyHash,
preload,
pin
})

print(cidToString(cid, { base: cidBase }))
})())
}
}
45 changes: 45 additions & 0 deletions src/cli/commands/dag/resolve.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict'

const CID = require('cids')

module.exports = {
command: 'resolve <ref>',

describe: 'fetches a dag node from ipfs, prints its address and remaining path',

builder: {
ref: {
type: 'string'
}
},

handler ({ ref, getIpfs, print, resolve }) {
resolve((async () => {
const ipfs = await getIpfs()
const options = {}

try {
const result = await ipfs.dag.resolve(ref, options)
let lastCid

for (const res of result) {
if (CID.isCID(res.value)) {
lastCid = res.value
}
}

if (!lastCid) {
if (ref.startsWith('/ipfs/')) {
ref = ref.substring(6)
}

lastCid = ref.split('/').shift()
}

print(lastCid.toString())
} catch (err) {
return print(`dag get resolve: ${err}`)
}
})())
}
}
112 changes: 59 additions & 53 deletions src/core/components/dag.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,50 @@ const all = require('async-iterator-all')
const errCode = require('err-code')
const multicodec = require('multicodec')

function parseArgs (cid, path, options) {
options = options || {}

// Allow options in path position
if (path !== undefined && typeof path !== 'string') {
options = path
path = undefined
}

if (typeof cid === 'string') {
if (cid.startsWith('/ipfs/')) {
cid = cid.substring(6)
}

const split = cid.split('/')

try {
cid = new CID(split[0])
} catch (err) {
throw errCode(err, 'ERR_INVALID_CID')
}

split.shift()

if (split.length > 0) {
path = split.join('/')
} else {
path = path || '/'
}
} else if (Buffer.isBuffer(cid)) {
try {
cid = new CID(cid)
} catch (err) {
throw errCode(err, 'ERR_INVALID_CID')
}
}

return [
cid,
path,
options
]
}

module.exports = function dag (self) {
return {
put: callbackify.variadic(async (dagNode, options) => {
Expand Down Expand Up @@ -53,41 +97,17 @@ module.exports = function dag (self) {
self._preload(cid)
}

if (pin) {
await ipfs.pin.add(cid, {
lock: true
})
}
Copy link
Member

Choose a reason for hiding this comment

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

We need to take the lock around the ipld.put and pin.add like we do in ipfs.add https://github.com/ipfs/js-ipfs/blob/master/src/core/components/files-regular/add-async-iterator.js#L58-L64

Note we'll need to call pin.add with lock: false in the same way we do with add.


return cid
}),

get: callbackify.variadic(async (cid, path, options) => {
options = options || {}

// Allow options in path position
if (path !== undefined && typeof path !== 'string') {
options = path
path = undefined
}

if (typeof cid === 'string') {
const split = cid.split('/')

try {
cid = new CID(split[0])
} catch (err) {
throw errCode(err, 'ERR_INVALID_CID')
}

split.shift()

if (split.length > 0) {
path = split.join('/')
} else {
path = path || '/'
}
} else if (Buffer.isBuffer(cid)) {
try {
cid = new CID(cid)
} catch (err) {
throw errCode(err, 'ERR_INVALID_CID')
}
}
[cid, path, options] = parseArgs(cid, path, options)

if (options.preload !== false) {
self._preload(cid)
Expand Down Expand Up @@ -116,37 +136,23 @@ module.exports = function dag (self) {
}),

tree: callbackify.variadic(async (cid, path, options) => { // eslint-disable-line require-await
options = options || {}
[cid, path, options] = parseArgs(cid, path, options)

// Allow options in path position
if (path !== undefined && typeof path !== 'string') {
options = path
path = undefined
if (options.preload !== false) {
self._preload(cid)
}

if (typeof cid === 'string') {
const split = cid.split('/')

try {
cid = new CID(split[0])
} catch (err) {
throw errCode(err, 'ERR_INVALID_CID')
}

split.shift()
return all(self._ipld.tree(cid, path, options))
}),

if (split.length > 0) {
path = split.join('/')
} else {
path = undefined
}
}
resolve: callbackify.variadic(async (cid, path, options) => { // eslint-disable-line require-await
[cid, path, options] = parseArgs(cid, path, options)

if (options.preload !== false) {
self._preload(cid)
}

return all(self._ipld.tree(cid, path, options))
return all(self._ipld.resolve(cid, path))
})
}
}
2 changes: 1 addition & 1 deletion test/cli/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
const { expect } = require('interface-ipfs-core/src/utils/mocha')
const runOnAndOff = require('../utils/on-and-off')

const commandCount = 98
const commandCount = 100
describe('commands', () => runOnAndOff((thing) => {
let ipfs

Expand Down
12 changes: 8 additions & 4 deletions test/cli/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ const daemonReady = (daemon) => {
reject(new Error('Daemon didn\'t start ' + data.toString('utf8')))
}
})

daemon.catch(err => {
reject(err)
})
})
}
const checkLock = (repo) => {
Expand Down Expand Up @@ -128,8 +132,8 @@ describe('daemon', () => {
]

await ipfs('init')
await ipfs('config', 'Addresses.API', JSON.stringify(apiAddrs), '--json')
await ipfs('config', 'Addresses.Gateway', JSON.stringify(gatewayAddrs), '--json')
await ipfs(`config Addresses.API ${JSON.stringify(apiAddrs)} --json`)
await ipfs(`config Addresses.Gateway ${JSON.stringify(gatewayAddrs)} --json`)

const daemon = ipfs('daemon')
let stdout = ''
Expand Down Expand Up @@ -157,8 +161,8 @@ describe('daemon', () => {
this.timeout(100 * 1000)

await ipfs('init')
await ipfs('config', 'Addresses.API', '[]', '--json')
await ipfs('config', 'Addresses.Gateway', '[]', '--json')
await ipfs('config Addresses.API [] --json')
await ipfs('config Addresses.Gateway [] --json')

const daemon = ipfs('daemon')
let stdout = ''
Expand Down
Loading