code refactor & sync bugfixes

This commit is contained in:
olcxja 2026-10-05 13:43:49 +02:00
commit 9edcc9841b
20 changed files with 820 additions and 812 deletions

View file

@ -4,6 +4,16 @@ const fs = require('fs')
const fsp = require('fs').promises
const path = require('path')
// accessSync instead of existsSync: same answer, one syscall fewer.
function pathExists(p) {
try {
fs.accessSync(p)
return true
} catch {
return false
}
}
// Returns a non-existing path in `base` named `name` (or `name (2)`, `name (3)`...).
function dedupeDir(base, name) {
const candidate = path.join(base, name)
@ -50,6 +60,22 @@ function progressGate(emit) {
return push
}
// Run `fn` over `items` with at most `limit` calls in flight, results in
// order. Walking a tree is dominated by stat/readlink/open syscalls: a few in
// flight keep the disk and cpu busy without exhausting file descriptors.
async function mapLimit(items, limit, fn) {
const out = new Array(items.length)
let next = 0
const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
while (next < items.length) {
const i = next++
out[i] = await fn(items[i], i)
}
})
await Promise.all(workers)
return out
}
// What a tree copy will have to move. Symlinks have no size of their own
// (they are recreated, not read), so they only count for the file total.
// `skipDir` is a single directory name to leave out (a game folder's
@ -218,5 +244,5 @@ async function removeTree(root, onProgress) {
return { files, dirs, bytes }
}
module.exports = { dedupeDir, copyTree, treeSize, removeTree, progressGate }
module.exports = { pathExists, dedupeDir, copyTree, treeSize, removeTree, progressGate, mapLimit }