Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

Commit e737977

Browse files
committed
feat: adds ls streaming methods
Implementation of ipfs-inactive/interface-js-ipfs-core#401 License: MIT Signed-off-by: achingbrain <[email protected]>
1 parent bc946c3 commit e737977

File tree

5 files changed

+206
-150
lines changed

5 files changed

+206
-150
lines changed

Diff for: src/cli/ls.js

+48-45
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
'use strict'
22

3+
const pull = require('pull-stream/pull')
4+
const onEnd = require('pull-stream/sinks/on-end')
5+
const through = require('pull-stream/throughs/through')
36
const {
47
print,
58
asBoolean
@@ -21,12 +24,12 @@ module.exports = {
2124
coerce: asBoolean,
2225
describe: 'Use long listing format.'
2326
},
24-
unsorted: {
25-
alias: 'U',
27+
sort: {
28+
alias: 's',
2629
type: 'boolean',
2730
default: false,
2831
coerce: asBoolean,
29-
describe: 'Do not sort; list entries in directory order.'
32+
describe: 'Sort entries by name'
3033
},
3134
'cid-base': {
3235
default: 'base58btc',
@@ -39,55 +42,55 @@ module.exports = {
3942
path,
4043
ipfs,
4144
long,
42-
unsorted,
45+
sort,
4346
cidBase
4447
} = argv
4548

4649
argv.resolve(
47-
ipfs.files.ls(path || FILE_SEPARATOR, {
48-
long,
49-
unsorted,
50-
cidBase
51-
})
52-
.then(files => {
53-
if (long) {
54-
const table = []
55-
const lengths = {}
56-
57-
files.forEach(link => {
58-
const row = {
59-
name: `${link.name}`,
60-
hash: `${link.hash}`,
61-
size: `${link.size}`
50+
new Promise((resolve, reject) => {
51+
if (sort) {
52+
ipfs.files.ls(path || FILE_SEPARATOR, {
53+
long,
54+
sort,
55+
cidBase
56+
})
57+
.then(files => {
58+
if (long) {
59+
files.forEach(link => {
60+
print(`${link.name}\t${link.hash}\t${link.size}`)
61+
})
62+
} else {
63+
files.forEach(link => print(link.name))
6264
}
6365

64-
Object.keys(row).forEach(key => {
65-
const value = row[key]
66-
67-
lengths[key] = lengths[key] > value.length ? lengths[key] : value.length
68-
})
69-
70-
table.push(row)
71-
})
72-
73-
table.forEach(row => {
74-
let line = ''
75-
76-
Object.keys(row).forEach(key => {
77-
const value = row[key]
78-
79-
line += value.padEnd(lengths[key])
80-
line += '\t'
81-
})
82-
83-
print(line)
66+
resolve()
8467
})
85-
86-
return
87-
}
88-
89-
files.forEach(link => print(link.name))
90-
})
68+
.catch(reject)
69+
70+
return
71+
}
72+
73+
pull(
74+
ipfs.files.lsPullStream(path, {
75+
long,
76+
cidBase
77+
}),
78+
through(file => {
79+
if (long) {
80+
print(`${file.name}\t${file.hash}\t${file.size}`)
81+
} else {
82+
print(file.name)
83+
}
84+
}),
85+
onEnd((error) => {
86+
if (error) {
87+
return reject(error)
88+
}
89+
90+
resolve()
91+
})
92+
)
93+
})
9194
)
9295
}
9396
}

Diff for: src/core/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ const unwrappedOperations = {
3030
// These operations are synchronous and manage their own locking
3131
const unwrappedSynchronousOperations = {
3232
readPullStream: require('./read-pull-stream'),
33-
readReadableStream: require('./read-readable-stream')
33+
readReadableStream: require('./read-readable-stream'),
34+
lsPullStream: require('./ls-pull-stream'),
35+
lsReadableStream: require('./ls-readable-stream')
3436
}
3537

3638
const wrap = ({

Diff for: src/core/ls-pull-stream.js

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
'use strict'
2+
3+
const waterfall = require('async/waterfall')
4+
const UnixFs = require('ipfs-unixfs')
5+
const exporter = require('ipfs-unixfs-exporter')
6+
const {
7+
loadNode,
8+
formatCid,
9+
toMfsPath,
10+
FILE_SEPARATOR,
11+
FILE_TYPES
12+
} = require('./utils')
13+
const pull = require('pull-stream/pull')
14+
const collect = require('pull-stream/sinks/collect')
15+
const asyncMap = require('pull-stream/throughs/async-map')
16+
const filter = require('pull-stream/throughs/filter')
17+
const once = require('pull-stream/sources/once')
18+
const error = require('pull-stream/sources/error')
19+
const defer = require('pull-defer')
20+
21+
const defaultOptions = {
22+
long: false,
23+
cidBase: 'base58btc'
24+
}
25+
26+
module.exports = (context) => {
27+
return function mfsLs (path, options = {}) {
28+
if (typeof path === 'object') {
29+
options = path
30+
path = FILE_SEPARATOR
31+
}
32+
33+
options = Object.assign({}, defaultOptions, options)
34+
35+
options.long = options.l || options.long
36+
37+
const deferred = defer.source()
38+
39+
waterfall([
40+
(cb) => toMfsPath(context, path, cb),
41+
({ mfsPath, depth }, cb) => {
42+
pull(
43+
exporter(mfsPath, context.ipld, {
44+
maxDepth: depth
45+
}),
46+
47+
collect((err, files) => {
48+
if (err) {
49+
return cb(err)
50+
}
51+
52+
if (files.length > 1) {
53+
return cb(new Error(`Path ${path} had ${files.length} roots`))
54+
}
55+
56+
const file = files[0]
57+
58+
if (!file) {
59+
return cb(new Error(`${path} does not exist`))
60+
}
61+
62+
if (file.type !== 'dir') {
63+
return cb(null, once(file))
64+
}
65+
66+
let first = true
67+
68+
return cb(null, pull(
69+
exporter(mfsPath, context.ipld, {
70+
maxDepth: depth + 1
71+
}),
72+
// first item in list is the directory node
73+
filter(() => {
74+
if (first) {
75+
first = false
76+
return false
77+
}
78+
79+
return true
80+
})
81+
))
82+
})
83+
)
84+
},
85+
(source, cb) => {
86+
cb(null,
87+
pull(
88+
source,
89+
90+
// load DAGNodes for each file
91+
asyncMap((file, cb) => {
92+
if (!options.long) {
93+
return cb(null, {
94+
name: file.name,
95+
type: 0,
96+
size: 0,
97+
hash: ''
98+
})
99+
}
100+
101+
loadNode(context, {
102+
cid: file.hash
103+
}, (err, result) => {
104+
if (err) {
105+
return cb(err)
106+
}
107+
108+
const meta = UnixFs.unmarshal(result.node.data)
109+
110+
cb(null, {
111+
name: file.name,
112+
type: FILE_TYPES[meta.type],
113+
hash: formatCid(file.hash, options.cidBase),
114+
size: meta.fileSize() || 0
115+
})
116+
})
117+
})
118+
)
119+
)
120+
}
121+
], (err, source) => {
122+
if (err) {
123+
return deferred.resolve(error(err))
124+
}
125+
126+
deferred.resolve(source)
127+
})
128+
129+
return deferred
130+
}
131+
}

Diff for: src/core/ls-readable-stream.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict'
2+
3+
const lsPullStream = require('./ls-pull-stream')
4+
const toStream = require('pull-stream-to-stream')
5+
6+
module.exports = (context) => {
7+
return function mfsLsReadableStream (path, options = {}) {
8+
return toStream.source(lsPullStream(context)(path, options))
9+
}
10+
}

0 commit comments

Comments
 (0)