diff --git a/src/cli/commands/pin/add.js b/src/cli/commands/pin/add.js index a0ff92806b..17238076e9 100644 --- a/src/cli/commands/pin/add.js +++ b/src/cli/commands/pin/add.js @@ -7,6 +7,13 @@ const log = debug('cli:pin') log.error = debug('cli:pin:error') const bs58 = require('bs58') +const onError = (err) => { + if (err) { + console.error(err) + throw err + } +} + module.exports = Command.extend({ desc: 'Pins objects to local storage.', @@ -21,53 +28,46 @@ module.exports = Command.extend({ run: (recursive, path) => { utils.getIPFS((err, ipfs) => { - if (err) { - console.error(err) - throw err - } - const matched = path.match(/^(?:\/ipfs\/)?([^\/]+(?:\/[^\/]+)*)\/?$/) - if (!matched) { - err = new Error('invalid ipfs ref path') - console.error(err) - throw err - } - const split = matched[1].split('/') - const rootHash = split[0] - const key = new Buffer(bs58.decode(rootHash)) - const links = split.slice(1, split.length) - const pathFn = (err, obj) => { - if (err) { - console.error(err) - throw err + onError(err) + // load persistent pin set from datastore + ipfs.pinner.load(() => { + const matched = path.match(/^(?:\/ipfs\/)?([^\/]+(?:\/[^\/]+)*)\/?$/) + if (!matched) { + onError(new Error('invalid ipfs ref path')) } - if (links.length) { - const linkName = links.shift() - const nextLink = obj.links.filter((link) => { - return (link.name === linkName) - }) - if (!nextLink.length) { - err = new Error( - 'pin: no link named ' + linkName + - ' under ' + obj.toJSON().Hash - ) - console.error(err) - throw err - } - const nextHash = nextLink[0].hash - ipfs.object.get(nextHash, pathFn) - } else { - ipfs.pinner.pin(obj, recursive, (err) => { - if (err) { - console.error(err) - throw err + const split = matched[1].split('/') + const rootHash = split[0] + const key = new Buffer(bs58.decode(rootHash)) + const links = split.slice(1, split.length) + const pathFn = (err, obj) => { + onError(err) + if (links.length) { + const linkName = links.shift() + const nextLink = obj.links.filter((link) => { + return (link.name === linkName) + }) + if (!nextLink.length) { + onError(new Error( + 'pin: no link named ' + linkName + + ' under ' + obj.toJSON().Hash + )) } - const mode = recursive ? ' recursively' : ' directly' - console.log('pinned ' + obj.toJSON().Hash + mode) - }) + const nextHash = nextLink[0].hash + ipfs.object.get(nextHash, pathFn) + } else { + ipfs.pinner.pin(obj, recursive, (err) => { + onError(err) + // save modified pin state to datastore + ipfs.pinner.flush((err, root) => { + onError(err) + const mode = recursive ? ' recursively' : ' directly' + console.log('pinned ' + obj.toJSON().Hash + mode) + }) + }) + } } - } - - ipfs.object.get(key, pathFn) + ipfs.object.get(key, pathFn) + }) }) } }) diff --git a/src/cli/commands/pin/rm.js b/src/cli/commands/pin/rm.js new file mode 100644 index 0000000000..79aa33a7ba --- /dev/null +++ b/src/cli/commands/pin/rm.js @@ -0,0 +1,71 @@ +'use strict' + +const Command = require('ronin').Command +const utils = require('../../utils') +const debug = require('debug') +const log = debug('cli:pin') +log.error = debug('cli:pin:error') +const bs58 = require('bs58') + +const onError = (err) => { + if (err) { + console.error(err) + throw err + } +} + +module.exports = Command.extend({ + desc: 'Removes the pinned object from local storage.', + + options: { + recursive: { + alias: 'r', + type: 'boolean', + default: true + } + }, + + run: (recursive, path) => { + utils.getIPFS((err, ipfs) => { + onError(err) + // load persistent pin set from datastore + ipfs.pinner.load(() => { + const matched = path.match(/^(?:\/ipfs\/)?([^\/]+(?:\/[^\/]+)*)\/?$/) + if (!matched) { + onError(new Error('invalid ipfs ref path')) + } + const split = matched[1].split('/') + const rootHash = split[0] + const key = new Buffer(bs58.decode(rootHash)) + const links = split.slice(1, split.length) + const pathFn = (err, obj) => { + onError(err) + if (links.length) { + const linkName = links.shift() + const nextLink = obj.links.filter((link) => { + return (link.name === linkName) + }) + if (!nextLink.length) { + onError(new Error( + 'pin: no link named ' + linkName + + ' under ' + obj.toJSON().Hash + )) + } + const nextHash = nextLink[0].hash + ipfs.object.get(nextHash, pathFn) + } else { + ipfs.pinner.unpin(obj.multihash(), recursive, (err) => { + onError(err) + // save modified pin state to datastore + ipfs.pinner.flush((err, root) => { + onError(err) + console.log('unpinned ' + obj.toJSON().Hash) + }) + }) + } + } + ipfs.object.get(key, pathFn) + }) + }) + } +}) diff --git a/test/cli/test-pin.js b/test/cli/test-pin.js index 3a7892a9f3..033015bb4b 100644 --- a/test/cli/test-pin.js +++ b/test/cli/test-pin.js @@ -54,5 +54,34 @@ describe('pin', function () { done() }) }) + it('add (direct)', (done) => { + nexpect.spawn('node', [bin, 'pin', 'add', '--recursive=false', + keys['leaf.json']], opts) + .run((err, stdout, exitcode) => { + expect(err).to.not.exist + expect(exitcode).to.equal(0) + expect(stdout[0]).to.equal('pinned ' + keys['leaf.json'] + ' directly') + done() + }) + }) + it('rm (recursively by default)', (done) => { + nexpect.spawn('node', [bin, 'pin', 'rm', rootHash], opts) + .run((err, stdout, exitcode) => { + expect(err).to.not.exist + expect(exitcode).to.equal(0) + expect(stdout[0]).to.equal('unpinned ' + rootHash) + done() + }) + }) + it('rm (direct)', (done) => { + nexpect.spawn('node', [bin, 'pin', 'rm', '--recursive=false', + keys['leaf.json']], opts) + .run((err, stdout, exitcode) => { + expect(err).to.not.exist + expect(exitcode).to.equal(0) + expect(stdout[0]).to.equal('unpinned ' + keys['leaf.json']) + done() + }) + }) }) })