get-list now produces ordered results
Massimo Melina committed
Apr 30, 2025 at 11:32 UTC
b63d0b4cce0c37feec2b751a51d87e7e26dc9975
3 files changed
+13
-7
src/serveGuiAndSharedFiles.ts
+1
-1
@@ -171,7 +171,7 @@ async function sendFolderList(node: VfsNode, ctx: Koa.Context) {
171
|| URL.protocol + '//' + URL.host + ctx.state.revProxyPath
172
prepend = base + pathEncode(decodeURI(ctx.path)) // redo the encoding our way, keeping unicode chars unchanged
173
}
174
- const walker = walkNode(node, { ctx, depth: depth === '*' ? Infinity : Number(depth) })
174
+ const walker = walkNode(node, { ctx, depth: depth === '*' ? Infinity : Number(depth), parallelizeRecursion: false })
175
ctx.body = asyncGeneratorToReadable(filterMapGenerator(walker, async el => {
176
const isFolder = await nodeIsDirectory(el)
177
return !folders && isFolder ? undefined
src/vfs.ts
+5
-3
@@ -275,7 +275,8 @@ interface WalkNodeOptions {
275
prefixPath?: string,
276
requiredPerm?: undefined | keyof VfsPerms,
277
onlyFolders?: boolean,
278
- onlyFiles?: boolean
278
+ onlyFiles?: boolean,
279
+ parallelizeRecursion?: boolean,
280
}
281
// it's the responsibility of the caller to verify you have list permission on parent, as callers have different needs.
282
export async function* walkNode(parent: VfsNode, {
@@ -285,6 +286,7 @@ export async function* walkNode(parent: VfsNode, {
286
requiredPerm,
287
onlyFolders = false,
288
onlyFiles = false,
289
+ parallelizeRecursion = true,
290
}: WalkNodeOptions = {}) {
291
let started = false
292
const stream = new Readable({
@@ -325,7 +327,7 @@ export async function* walkNode(parent: VfsNode, {
327
try {
328
let lastDir = prefixPath.slice(0, -1) || '.'
329
parentsCache.set(lastDir, parent)
328
- await walkDir(source, { depth, ctx, hidden: showHiddenFiles.get() }, async entry => {
330
+ await walkDir(source, { depth, ctx, hidden: showHiddenFiles.get(), parallelizeRecursion }, async entry => {
331
if (ctx?.isAborted()) {
332
stream.push(null)
333
return null
@@ -368,7 +370,7 @@ export async function* walkNode(parent: VfsNode, {
370
}
371
finally {
372
for (const [item, name] of visitLater)
371
- for await (const x of walkNode(item, { ctx, depth: depth - 1, prefixPath: name + '/', requiredPerm, onlyFolders }))
373
+ for await (const x of walkNode(item, { depth: depth - 1, prefixPath: name + '/', ctx, requiredPerm, onlyFolders, parallelizeRecursion }))
374
stream.push(x)
375
stream.push(null)
376
}
src/walkDir.ts
+7
-3
@@ -18,9 +18,10 @@ export interface DirStreamEntry extends Dirent {
18
const dirQ = makeQ(3)
19
20
// cb returns void = just go on, null = stop, false = go on but don't recur (in case of depth)
21
-export function walkDir(path: string, { depth = 0, hidden = true, ctx }: {
21
+export function walkDir(path: string, { depth = 0, hidden = true, parallelizeRecursion = false, ctx }: {
22
depth?: number,
23
hidden?: boolean,
24
+ parallelizeRecursion?: boolean,
25
ctx?: Context
26
}, cb: (e: DirStreamEntry) => Promisable<void | null | false>) {
27
let stopped = false
@@ -99,6 +100,7 @@ export function walkDir(path: string, { depth = 0, hidden = true, ctx }: {
100
n++
101
if (!depth || !entry.isDirectory()) return
102
const branchDone = pendingPromise() // per-job
103
+ subDirsDone.push(branchDone)
104
const job = () =>
105
readDir(entry.path, depth - 1) // recur
106
.then(x => x, () => {}) // mute errors
@@ -108,8 +110,10 @@ export function walkDir(path: string, { depth = 0, hidden = true, ctx }: {
110
Promise.resolve(res?.branchDone).then(() =>
111
branchDone.resolve())
112
})
111
- dirQ.add(job) // this won't start until next tick
112
- subDirsDone.push(branchDone)
113
+ if (parallelizeRecursion)
114
+ dirQ.add(job)
115
+ else
116
+ await job()
117
}
118
}
119
}