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

Commit c30f1e7

Browse files
committed
Pinning core and cli
1 parent 78653b3 commit c30f1e7

File tree

13 files changed

+1296
-0
lines changed

13 files changed

+1296
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"bs58": "^3.0.0",
6464
"debug": "^2.2.0",
6565
"detect-node": "^2.0.3",
66+
"fnv": "^0.1.3",
6667
"fs-blob-store": "^5.2.1",
6768
"glob": "^7.0.3",
6869
"hapi": "^13.4.1",

src/cli/commands/pin/add.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'use strict'
2+
3+
const Command = require('ronin').Command
4+
const utils = require('../../utils')
5+
const debug = require('debug')
6+
const log = debug('cli:pin')
7+
log.error = debug('cli:pin:error')
8+
const bs58 = require('bs58')
9+
10+
const onError = (err) => {
11+
if (err) {
12+
console.error(err)
13+
throw err
14+
}
15+
}
16+
17+
module.exports = Command.extend({
18+
desc: 'Pins objects to local storage.',
19+
20+
options: {
21+
// Recursively pin the object linked to by the specified object(s)
22+
recursive: {
23+
alias: 'r',
24+
type: 'boolean',
25+
default: true
26+
}
27+
},
28+
29+
run: (recursive, path) => {
30+
utils.getIPFS((err, ipfs) => {
31+
onError(err)
32+
// load persistent pin set from datastore
33+
ipfs.pinner.load(() => {
34+
const matched = path.match(/^(?:\/ipfs\/)?([^\/]+(?:\/[^\/]+)*)\/?$/)
35+
if (!matched) {
36+
onError(new Error('invalid ipfs ref path'))
37+
}
38+
const split = matched[1].split('/')
39+
const rootHash = split[0]
40+
const key = new Buffer(bs58.decode(rootHash))
41+
const links = split.slice(1, split.length)
42+
const pathFn = (err, obj) => {
43+
onError(err)
44+
if (links.length) {
45+
const linkName = links.shift()
46+
const nextLink = obj.links.filter((link) => {
47+
return (link.name === linkName)
48+
})
49+
if (!nextLink.length) {
50+
onError(new Error(
51+
'pin: no link named ' + linkName +
52+
' under ' + obj.toJSON().Hash
53+
))
54+
}
55+
const nextHash = nextLink[0].hash
56+
ipfs.object.get(nextHash, pathFn)
57+
} else {
58+
ipfs.pinner.pin(obj, recursive, (err) => {
59+
onError(err)
60+
// save modified pin state to datastore
61+
ipfs.pinner.flush((err, root) => {
62+
onError(err)
63+
const mode = recursive ? ' recursively' : ' directly'
64+
console.log('pinned ' + obj.toJSON().Hash + mode)
65+
})
66+
})
67+
}
68+
}
69+
ipfs.object.get(key, pathFn)
70+
})
71+
})
72+
}
73+
})

src/cli/commands/pin/ls.js

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

src/cli/commands/pin/rm.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
'use strict'
2+
3+
const Command = require('ronin').Command
4+
const utils = require('../../utils')
5+
const debug = require('debug')
6+
const log = debug('cli:pin')
7+
log.error = debug('cli:pin:error')
8+
const bs58 = require('bs58')
9+
10+
const onError = (err) => {
11+
if (err) {
12+
console.error(err)
13+
throw err
14+
}
15+
}
16+
17+
module.exports = Command.extend({
18+
desc: 'Removes the pinned object from local storage.',
19+
20+
options: {
21+
recursive: {
22+
alias: 'r',
23+
type: 'boolean',
24+
default: true
25+
}
26+
},
27+
28+
run: (recursive, path) => {
29+
utils.getIPFS((err, ipfs) => {
30+
onError(err)
31+
// load persistent pin set from datastore
32+
ipfs.pinner.load(() => {
33+
const matched = path.match(/^(?:\/ipfs\/)?([^\/]+(?:\/[^\/]+)*)\/?$/)
34+
if (!matched) {
35+
onError(new Error('invalid ipfs ref path'))
36+
}
37+
const split = matched[1].split('/')
38+
const rootHash = split[0]
39+
const key = new Buffer(bs58.decode(rootHash))
40+
const links = split.slice(1, split.length)
41+
const pathFn = (err, obj) => {
42+
onError(err)
43+
if (links.length) {
44+
const linkName = links.shift()
45+
const nextLink = obj.links.filter((link) => {
46+
return (link.name === linkName)
47+
})
48+
if (!nextLink.length) {
49+
onError(new Error(
50+
'pin: no link named ' + linkName +
51+
' under ' + obj.toJSON().Hash
52+
))
53+
}
54+
const nextHash = nextLink[0].hash
55+
ipfs.object.get(nextHash, pathFn)
56+
} else {
57+
ipfs.pinner.isPinned(obj.multihash(), (err, pinned, reason) => {
58+
onError(err)
59+
if (!pinned) {
60+
onError(new Error('not pinned'))
61+
}
62+
ipfs.pinner.unpin(obj.multihash(), recursive, (err) => {
63+
onError(err)
64+
// save modified pin state to datastore
65+
ipfs.pinner.flush((err, root) => {
66+
onError(err)
67+
console.log('unpinned ' + obj.toJSON().Hash)
68+
})
69+
})
70+
})
71+
}
72+
}
73+
ipfs.object.get(key, pathFn)
74+
})
75+
})
76+
}
77+
})

src/core/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const repo = require('./ipfs/repo')
1717
const init = require('./ipfs/init')
1818
const bootstrap = require('./ipfs/bootstrap')
1919
const config = require('./ipfs/config')
20+
const pinner = require('./ipfs/pinner')
2021
const block = require('./ipfs/block')
2122
const object = require('./ipfs/object')
2223
const libp2p = require('./ipfs/libp2p')
@@ -53,6 +54,7 @@ function IPFS (repoInstance) {
5354
this.init = init(this)
5455
this.bootstrap = bootstrap(this)
5556
this.config = config(this)
57+
this.pinner = pinner(this)
5658
this.block = block(this)
5759
this.object = object(this)
5860
this.libp2p = libp2p(this)

0 commit comments

Comments
 (0)