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

Commit 95384e9

Browse files
committed
Pinning core, cli and http
1 parent 676b354 commit 95384e9

File tree

19 files changed

+1729
-0
lines changed

19 files changed

+1729
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"bs58": "^3.0.0",
6565
"debug": "^2.2.0",
6666
"detect-node": "^2.0.3",
67+
"fnv1a": "^1.0.1",
6768
"fs-blob-store": "^5.2.1",
6869
"glob": "^7.0.5",
6970
"hapi": "^14.0.0",

src/cli/commands/pin.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict'
2+
3+
module.exports = {
4+
command: 'pin',
5+
6+
description: 'Pin and unpin objects to local storage.',
7+
8+
builder (yargs) {
9+
return yargs
10+
.commandDir('pin')
11+
},
12+
13+
handler (argv) {
14+
}
15+
}

src/cli/commands/pin/add.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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: 'add <ipfs-path>',
18+
19+
describe: 'Pins objects to local storage.',
20+
21+
builder: {
22+
recursive: {
23+
type: 'boolean',
24+
alias: 'r',
25+
default: true,
26+
describe: 'Recursively pin the object linked to by the specified object(s).'
27+
}
28+
},
29+
30+
handler (argv) {
31+
const path = argv['ipfs-path']
32+
const recursive = argv.recursive
33+
utils.getIPFS((err, ipfs) => {
34+
onError(err)
35+
// load persistent pin set from datastore
36+
ipfs.pinner.load(() => {
37+
const matched = path.match(/^(?:\/ipfs\/)?([^\/]+(?:\/[^\/]+)*)\/?$/)
38+
if (!matched) {
39+
onError(new Error('invalid ipfs ref path'))
40+
}
41+
const split = matched[1].split('/')
42+
const rootHash = split[0]
43+
const key = new Buffer(bs58.decode(rootHash))
44+
const links = split.slice(1, split.length)
45+
const pathFn = (err, obj) => {
46+
onError(err)
47+
if (links.length) {
48+
const linkName = links.shift()
49+
const nextLink = obj.links.filter((link) => {
50+
return (link.name === linkName)
51+
})
52+
if (!nextLink.length) {
53+
onError(new Error(
54+
'pin: no link named ' + linkName +
55+
' under ' + obj.toJSON().Hash
56+
))
57+
}
58+
const nextHash = nextLink[0].hash
59+
ipfs.object.get(nextHash, pathFn)
60+
} else {
61+
ipfs.pinner.pin(obj, recursive, (err) => {
62+
onError(err)
63+
// save modified pin state to datastore
64+
ipfs.pinner.flush((err, root) => {
65+
onError(err)
66+
const mode = recursive ? ' recursively' : ' directly'
67+
console.log('pinned ' + obj.toJSON().Hash + mode)
68+
})
69+
})
70+
}
71+
}
72+
ipfs.object.get(key, pathFn)
73+
})
74+
})
75+
}
76+
}

src/cli/commands/pin/ls.js

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
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+
}

src/cli/commands/pin/rm.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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: 'rm <ipfs-path>',
18+
19+
describe: 'Removes the pinned object from local storage.',
20+
21+
builder: {
22+
recursive: {
23+
type: 'boolean',
24+
alias: 'r',
25+
default: true,
26+
describe: 'Recursively unpin the objects linked to by the specified object(s).'
27+
}
28+
},
29+
30+
handler: (argv) => {
31+
const path = argv['ipfs-path']
32+
const recursive = argv.recursive
33+
utils.getIPFS((err, ipfs) => {
34+
onError(err)
35+
// load persistent pin set from datastore
36+
ipfs.pinner.load(() => {
37+
const matched = path.match(/^(?:\/ipfs\/)?([^\/]+(?:\/[^\/]+)*)\/?$/)
38+
if (!matched) {
39+
onError(new Error('invalid ipfs ref path'))
40+
}
41+
const split = matched[1].split('/')
42+
const rootHash = split[0]
43+
const key = new Buffer(bs58.decode(rootHash))
44+
const links = split.slice(1, split.length)
45+
const pathFn = (err, obj) => {
46+
onError(err)
47+
if (links.length) {
48+
const linkName = links.shift()
49+
const nextLink = obj.links.filter((link) => {
50+
return (link.name === linkName)
51+
})
52+
if (!nextLink.length) {
53+
onError(new Error(
54+
'pin: no link named ' + linkName +
55+
' under ' + obj.toJSON().Hash
56+
))
57+
}
58+
const nextHash = nextLink[0].hash
59+
ipfs.object.get(nextHash, pathFn)
60+
} else {
61+
ipfs.pinner.isPinned(obj.multihash(), (err, pinned, reason) => {
62+
onError(err)
63+
if (!pinned) {
64+
onError(new Error('not pinned'))
65+
}
66+
ipfs.pinner.unpin(obj.multihash(), recursive, (err) => {
67+
onError(err)
68+
// save modified pin state to datastore
69+
ipfs.pinner.flush((err, root) => {
70+
onError(err)
71+
console.log('unpinned ' + obj.toJSON().Hash)
72+
})
73+
})
74+
})
75+
}
76+
}
77+
ipfs.object.get(key, pathFn)
78+
})
79+
})
80+
}
81+
}

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)