| 
 | 1 | +'use strict'  | 
 | 2 | + | 
 | 3 | +const utils = require('../../utils')  | 
 | 4 | +const bs58 = require('bs58')  | 
 | 5 | +const debug = require('debug')  | 
 | 6 | +const log = debug('cli:pin')  | 
 | 7 | +log.error = debug('cli:pin:error')  | 
 | 8 | + | 
 | 9 | +const onError = (err) => {  | 
 | 10 | +  if (err) {  | 
 | 11 | +    console.error(err)  | 
 | 12 | +    throw err  | 
 | 13 | +  }  | 
 | 14 | +}  | 
 | 15 | + | 
 | 16 | +module.exports = {  | 
 | 17 | +  command: 'ls',  | 
 | 18 | + | 
 | 19 | +  describe: 'List objects pinned to local storage.',  | 
 | 20 | + | 
 | 21 | +  builder: {  | 
 | 22 | +    path: {  | 
 | 23 | +      type: 'string',  | 
 | 24 | +      describe: 'List pinned state of specific <ipfs-path>.'  | 
 | 25 | +    },  | 
 | 26 | +    type: {  | 
 | 27 | +      type: 'string',  | 
 | 28 | +      alias: 't',  | 
 | 29 | +      default: 'all',  | 
 | 30 | +      describe: ('The type of pinned keys to list. ' +  | 
 | 31 | +                 'Can be "direct", "indirect", "recursive", or "all".')  | 
 | 32 | +    },  | 
 | 33 | +    quiet: {  | 
 | 34 | +      type: 'boolean',  | 
 | 35 | +      alias: 'q',  | 
 | 36 | +      default: false,  | 
 | 37 | +      describe: 'Write just hashes of objects.'  | 
 | 38 | +    }  | 
 | 39 | +  },  | 
 | 40 | + | 
 | 41 | +  handler: (argv) => {  | 
 | 42 | +    const path = argv.path  | 
 | 43 | +    const type = argv.type  | 
 | 44 | +    const quiet = argv.quiet  | 
 | 45 | +    utils.getIPFS((err, ipfs) => {  | 
 | 46 | +      onError(err)  | 
 | 47 | +      const types = ipfs.pinner.types  | 
 | 48 | +      // load persistent pin set from datastore  | 
 | 49 | +      ipfs.pinner.load(() => {  | 
 | 50 | +        if (path) {  | 
 | 51 | +          const matched = path.match(/^(?:\/ipfs\/)?([^\/]+(?:\/[^\/]+)*)\/?$/)  | 
 | 52 | +          if (!matched) {  | 
 | 53 | +            onError(new Error('invalid ipfs ref path'))  | 
 | 54 | +          }  | 
 | 55 | +          const split = matched[1].split('/')  | 
 | 56 | +          const rootHash = split[0]  | 
 | 57 | +          const key = new Buffer(bs58.decode(rootHash))  | 
 | 58 | +          const links = split.slice(1, split.length)  | 
 | 59 | +          const pathFn = (err, obj) => {  | 
 | 60 | +            onError(err)  | 
 | 61 | +            if (links.length) {  | 
 | 62 | +              const linkName = links.shift()  | 
 | 63 | +              const nextLink = obj.links.filter((link) => {  | 
 | 64 | +                return (link.name === linkName)  | 
 | 65 | +              })  | 
 | 66 | +              if (!nextLink.length) {  | 
 | 67 | +                onError(new Error(  | 
 | 68 | +                  'pin: no link named ' + linkName +  | 
 | 69 | +                  ' under ' + obj.toJSON().Hash  | 
 | 70 | +                ))  | 
 | 71 | +              }  | 
 | 72 | +              const nextHash = nextLink[0].hash  | 
 | 73 | +              ipfs.object.get(nextHash, pathFn)  | 
 | 74 | +            } else {  | 
 | 75 | +              ipfs.pinner.isPinnedWithType(obj.multihash(), type, (err, pinned, reason) => {  | 
 | 76 | +                onError(err)  | 
 | 77 | +                if (!pinned) {  | 
 | 78 | +                  onError(new Error('Path ' + path + ' is not pinned'))  | 
 | 79 | +                }  | 
 | 80 | +                if (reason !== types.direct &&  | 
 | 81 | +                    reason !== types.recursive) {  | 
 | 82 | +                  reason = 'indirect through ' + reason  | 
 | 83 | +                }  | 
 | 84 | +                console.log(obj.toJSON().Hash + (quiet ? '' : ' ' + reason))  | 
 | 85 | +              })  | 
 | 86 | +            }  | 
 | 87 | +          }  | 
 | 88 | +          ipfs.object.get(key, pathFn)  | 
 | 89 | +        } else {  | 
 | 90 | +          const printDirect = () => {  | 
 | 91 | +            ipfs.pinner.directKeyStrings().forEach((key) => {  | 
 | 92 | +              console.log(key + (quiet ? '' : ' direct'))  | 
 | 93 | +            })  | 
 | 94 | +          }  | 
 | 95 | +          const printRecursive = () => {  | 
 | 96 | +            ipfs.pinner.recursiveKeyStrings().forEach((key) => {  | 
 | 97 | +              console.log(key + (quiet ? '' : ' recursive'))  | 
 | 98 | +            })  | 
 | 99 | +          }  | 
 | 100 | +          const printIndirect = () => {  | 
 | 101 | +            ipfs.pinner.getIndirectKeys((err, keys) => {  | 
 | 102 | +              onError(err)  | 
 | 103 | +              keys.forEach((key) => {  | 
 | 104 | +                console.log(key + (quiet ? '' : ' indirect'))  | 
 | 105 | +              })  | 
 | 106 | +            })  | 
 | 107 | +          }  | 
 | 108 | +          switch (type) {  | 
 | 109 | +            case types.direct:  | 
 | 110 | +              printDirect()  | 
 | 111 | +              break  | 
 | 112 | +            case types.recursive:  | 
 | 113 | +              printRecursive()  | 
 | 114 | +              break  | 
 | 115 | +            case types.indirect:  | 
 | 116 | +              printIndirect()  | 
 | 117 | +              break  | 
 | 118 | +            case types.all:  | 
 | 119 | +              printDirect()  | 
 | 120 | +              printRecursive()  | 
 | 121 | +              printIndirect()  | 
 | 122 | +              break  | 
 | 123 | +            default:  | 
 | 124 | +              onError(new Error(  | 
 | 125 | +                "Invalid type '" + type + "', " +  | 
 | 126 | +                'must be one of {direct, indirect, recursive, all}'  | 
 | 127 | +              ))  | 
 | 128 | +          }  | 
 | 129 | +        }  | 
 | 130 | +      })  | 
 | 131 | +    })  | 
 | 132 | +  }  | 
 | 133 | +}  | 
0 commit comments