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

Implement ipfs refs #2004

Merged
merged 28 commits into from
May 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8b36a48
feat: implement ipfs refs
dirkmc Apr 22, 2019
71ec3f1
feat: refs support in http api
dirkmc Apr 24, 2019
89f9b8c
feat: use ipld instead of unix-fs-exporter for refs
dirkmc Apr 28, 2019
67f3a84
test: add basic refs test
dirkmc Apr 29, 2019
8c09c8c
feat: refs local
dirkmc Apr 30, 2019
12b4b60
feat: add refs.localPullStream && refs.localReadableStream
dirkmc May 1, 2019
b0564a1
chore: change Ref -> ref
dirkmc May 2, 2019
00b38c6
feat: make object.links work with CBOR
dirkmc May 3, 2019
425447a
feat: handle multiple refs. Better param handling
dirkmc May 3, 2019
1129e4c
fix: print refs errors to stderr
dirkmc May 3, 2019
348b1e2
chore: add comment to explain cli param parsing
dirkmc May 8, 2019
1e9aff9
refactor: use streaming for refs local
dirkmc May 8, 2019
1d81be8
chore: update interface-ipfs-core package
dirkmc May 8, 2019
bf9fdff
refactor: cleaner refs param handling
dirkmc May 9, 2019
e8b76b4
fix: alias 'refs local' to 'refs-local'
dirkmc May 9, 2019
762aff0
refactor: move links retrieval from object to refs
dirkmc May 9, 2019
3416564
chore: add missing packages
dirkmc May 9, 2019
f991388
refactor: use streaming for cli refs and refs local
dirkmc May 13, 2019
5e5cd59
fix: add refs and refs local to command count
dirkmc May 13, 2019
07e4267
fix: refs in browser
dirkmc May 14, 2019
b55cfde
fix: restore param parsing behaviour
dirkmc May 14, 2019
e663075
chore: update interface-ipfs-core
dirkmc May 14, 2019
c731ddf
chore: update http-client
dirkmc May 15, 2019
6ac01e5
chore: update interface-ipfs-core
dirkmc May 15, 2019
6b002ac
fix: skip failing config.set test for now
dirkmc May 16, 2019
0fc81e5
fix: skip failing config.set test in http-api
dirkmc May 16, 2019
a6bc527
chore: update interface-ipfs-core and ipfs-http-client
dirkmc May 16, 2019
384c5de
chore: fix ipfs-http-client version
dirkmc May 16, 2019
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
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"execa": "^1.0.0",
"form-data": "^2.3.3",
"hat": "0.0.3",
"interface-ipfs-core": "~0.99.1",
"interface-ipfs-core": "~0.101.1",
"ipfsd-ctl": "~0.42.0",
"libp2p-websocket-star": "~0.10.2",
"ncp": "^2.0.0",
Expand All @@ -86,6 +86,7 @@
"@hapi/hapi": "^18.3.1",
"@hapi/joi": "^15.0.1",
"async": "^2.6.1",
"base32.js": "~0.1.0",
"bignumber.js": "^8.0.2",
"binary-querystring": "~0.1.2",
"bl": "^3.0.0",
Expand All @@ -112,7 +113,7 @@
"ipfs-bitswap": "~0.23.0",
"ipfs-block": "~0.8.0",
"ipfs-block-service": "~0.15.1",
"ipfs-http-client": "^31.0.0",
"ipfs-http-client": "^31.0.2",
"ipfs-http-response": "~0.2.1",
"ipfs-mfs": "~0.10.2",
"ipfs-multipart": "~0.1.0",
Expand Down Expand Up @@ -175,6 +176,7 @@
"pull-sort": "^1.0.1",
"pull-stream": "^3.6.9",
"pull-stream-to-stream": "^1.3.4",
"pull-traverse": "^1.0.3",
"readable-stream": "^3.1.1",
"receptacle": "^1.3.2",
"stream-to-pull-stream": "^1.7.3",
Expand Down
4 changes: 4 additions & 0 deletions src/cli/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const mfs = require('ipfs-mfs/cli')
const debug = require('debug')('ipfs:cli')
const pkg = require('../../package.json')
const parser = require('./parser')
const commandAlias = require('./command-alias')

async function main (args) {
const oneWeek = 1000 * 60 * 60 * 24 * 7
Expand All @@ -22,6 +23,9 @@ async function main (args) {

let getIpfs = null

// Apply command aliasing (eg `refs local` -> `refs-local`)
args = commandAlias(args)

cli
.parse(args)
.then(({ data, argv }) => {
Expand Down
35 changes: 35 additions & 0 deletions src/cli/command-alias.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict'

const aliases = {
// We need to be able to show help text for both the `refs` command and the
// `refs local` command, but with yargs `refs` cannot be both a command and
// a command directory. So alias `refs local` to `refs-local`
'refs-local': ['refs', 'local']
}

// Replace multi-word command with alias
// eg replace `refs local` with `refs-local`
module.exports = function (args) {
for (const [alias, original] of Object.entries(aliases)) {
if (arrayMatch(args, original)) {
return [alias, ...args.slice(original.length)]
}
}

return args
}

// eg arrayMatch([1, 2, 3], [1, 2]) => true
function arrayMatch (arr, sub) {
if (sub.length > arr.length) {
return false
}

for (let i = 0; i < sub.length; i++) {
if (arr[i] !== sub[i]) {
return false
}
}

return true
}
30 changes: 30 additions & 0 deletions src/cli/commands/refs-local.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict'

const { print } = require('../utils')

module.exports = {
command: 'refs-local',
Copy link
Member

Choose a reason for hiding this comment

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

We should be able to use this as ipfs refs local i.e. without the hyphen

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@alanshaw it seems like it will be tricky to make the parser work with both
ipfs refs <path>
ipfs refs local

I can probably hack it to make it work, but before I do that do you think it would make more sense to the user to give the commands different names instead?

Copy link
Member

Choose a reason for hiding this comment

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

Lets keep compat with go-ipfs - it's not too hacky to detect when path === 'local' and do the right thing in the refs handler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That part is easy, it's making the command line parser / help text auto-formatter understand it that will be a little trickier, I'll see if I can make it work

Copy link
Member

@alanshaw alanshaw May 8, 2019

Choose a reason for hiding this comment

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

Good point, please take a look but if it's going to be a big time sink or over complicated then lets forget it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a command aliaser at the beginning of parsing (unfortunately it's not possible to do with yargs middleware): https:/ipfs/js-ipfs/pull/2004/files#diff-71bd1bde77e38a68f76195b8f85ce19c


describe: 'List all local references.',

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

return new Promise((resolve, reject) => {
const stream = ipfs.refs.localReadableStream()

stream.on('error', reject)
stream.on('end', resolve)

stream.on('data', (ref) => {
if (ref.err) {
print(ref.err, true, true)
} else {
print(ref.ref)
}
})
})
})())
}
}
65 changes: 65 additions & 0 deletions src/cli/commands/refs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict'

const { print } = require('../utils')

module.exports = {
command: 'refs <key> [keys..]',

describe: 'List links (references) from an object',

builder: {
recursive: {
alias: 'r',
desc: 'Recursively list links of child nodes.',
type: 'boolean',
default: false
},
format: {
desc: 'Output edges with given format. Available tokens: <src> <dst> <linkname>.',
type: 'string',
default: '<dst>'
},
edges: {
alias: 'e',
desc: 'Output edge format: `<from> -> <to>`',
type: 'boolean',
default: false
},
unique: {
alias: 'u',
desc: 'Omit duplicate refs from output.',
type: 'boolean',
default: false
},
'max-depth': {
desc: 'Only for recursive refs, limits fetch and listing to the given depth.',
type: 'number'
}
},

handler ({ getIpfs, key, keys, recursive, format, edges, unique, maxDepth, resolve }) {
resolve((async () => {
if (maxDepth === 0) {
return
}

const ipfs = await getIpfs()
const k = [key].concat(keys)

return new Promise((resolve, reject) => {
const stream = ipfs.refsReadableStream(k, { recursive, format, edges, unique, maxDepth })

stream.on('error', reject)
stream.on('end', resolve)

stream.on('data', (ref) => {
if (ref.err) {
print(ref.err, true, true)
} else {
print(ref.ref)
}
})
})
})())
}
}
5 changes: 3 additions & 2 deletions src/cli/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ exports.getRepoPath = () => {
let visible = true
exports.disablePrinting = () => { visible = false }

exports.print = (msg, newline) => {
exports.print = (msg, newline, isError = false) => {
if (newline === undefined) {
newline = true
}
Expand All @@ -91,7 +91,8 @@ exports.print = (msg, newline) => {
msg = ''
}
msg = newline ? msg + '\n' : msg
process.stdout.write(msg)
const outStream = isError ? process.stderr : process.stdout
outStream.write(msg)
}
}

Expand Down
43 changes: 26 additions & 17 deletions src/core/components/files-regular/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
'use strict'

module.exports = self => ({
add: require('./add')(self),
addFromFs: require('./add-from-fs')(self),
addFromStream: require('./add-from-stream')(self),
addFromURL: require('./add-from-url')(self),
addPullStream: require('./add-pull-stream')(self),
addReadableStream: require('./add-readable-stream')(self),
cat: require('./cat')(self),
catPullStream: require('./cat-pull-stream')(self),
catReadableStream: require('./cat-readable-stream')(self),
get: require('./get')(self),
getPullStream: require('./get-pull-stream')(self),
getReadableStream: require('./get-readable-stream')(self),
ls: require('./ls')(self),
lsPullStream: require('./ls-pull-stream')(self),
lsReadableStream: require('./ls-readable-stream')(self)
})
module.exports = (self) => {
const filesRegular = {
add: require('./add')(self),
addFromFs: require('./add-from-fs')(self),
addFromStream: require('./add-from-stream')(self),
addFromURL: require('./add-from-url')(self),
addPullStream: require('./add-pull-stream')(self),
addReadableStream: require('./add-readable-stream')(self),
cat: require('./cat')(self),
catPullStream: require('./cat-pull-stream')(self),
catReadableStream: require('./cat-readable-stream')(self),
get: require('./get')(self),
getPullStream: require('./get-pull-stream')(self),
getReadableStream: require('./get-readable-stream')(self),
ls: require('./ls')(self),
lsPullStream: require('./ls-pull-stream')(self),
lsReadableStream: require('./ls-readable-stream')(self),
refs: require('./refs')(self),
refsReadableStream: require('./refs-readable-stream')(self),
refsPullStream: require('./refs-pull-stream')(self)
}
filesRegular.refs.local = require('./refs-local')(self)
filesRegular.refs.localReadableStream = require('./refs-local-readable-stream')(self)
filesRegular.refs.localPullStream = require('./refs-local-pull-stream')(self)
return filesRegular
}
34 changes: 34 additions & 0 deletions src/core/components/files-regular/refs-local-pull-stream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict'

const CID = require('cids')
const base32 = require('base32.js')
const pull = require('pull-stream')
const pullDefer = require('pull-defer')

module.exports = function (self) {
return () => {
const deferred = pullDefer.source()

self._repo.blocks.query({ keysOnly: true }, (err, blocks) => {
if (err) {
return deferred.resolve(pull.error(err))
}

const refs = blocks.map(b => dsKeyToRef(b.key))
deferred.resolve(pull.values(refs))
})

return deferred
}
}

function dsKeyToRef (key) {
try {
// Block key is of the form /<base32 encoded string>
const decoder = new base32.Decoder()
const buff = Buffer.from(decoder.write(key.toString().slice(1)).finalize())
return { ref: new CID(buff).toString() }
} catch (err) {
return { err: `Could not convert block with key '${key}' to CID: ${err.message}` }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict'

const toStream = require('pull-stream-to-stream')

module.exports = function (self) {
return (ipfsPath, options) => {
return toStream.source(self.refs.localPullStream())
}
}
18 changes: 18 additions & 0 deletions src/core/components/files-regular/refs-local.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict'

const promisify = require('promisify-es6')
const pull = require('pull-stream')

module.exports = function (self) {
return promisify((callback) => {
pull(
self.refs.localPullStream(),
pull.collect((err, values) => {
if (err) {
return callback(err)
}
callback(null, values)
})
)
})
}
Loading