cleanup comments, update translations, bump to 0.4.1
This commit is contained in:
parent
9edcc9841b
commit
7d8ab87eee
28 changed files with 412 additions and 1114 deletions
|
|
@ -23,11 +23,7 @@ function dedupeDir(base, name) {
|
|||
return path.join(base, `${name} (${n})`)
|
||||
}
|
||||
|
||||
// Progress is cheap to produce and expensive to render: hashing or copying a
|
||||
// tree can emit tens of thousands of events, and forwarding every single one
|
||||
// over IPC makes the window stutter instead of showing progress. Events are
|
||||
// rate limited to ~10/s; `force` lets a caller push the value that matters
|
||||
// (the end of a unit) through immediately.
|
||||
// Events are rate limited to ~10/s; `force` pushes the final value through.
|
||||
const PROGRESS_MIN_MS = 100
|
||||
|
||||
function progressGate(emit) {
|
||||
|
|
@ -60,9 +56,7 @@ 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.
|
||||
// Run `fn` over `items` with at most `limit` in flight, results in order.
|
||||
async function mapLimit(items, limit, fn) {
|
||||
const out = new Array(items.length)
|
||||
let next = 0
|
||||
|
|
@ -76,15 +70,12 @@ async function mapLimit(items, limit, fn) {
|
|||
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
|
||||
// redistributables) - walking the whole tree first is fast next to the copy.
|
||||
// What a tree copy will move. Symlinks are recreated, not read. `skipDir`
|
||||
// leaves out one directory name (redistributables).
|
||||
async function treeSize(root) {
|
||||
let files = 0
|
||||
let bytes = 0
|
||||
// a symlink (or a plain file) as the root is the whole tree: walking it
|
||||
// would measure whatever it points at, not what is about to be removed
|
||||
// a symlinked root is the whole tree; never measure through it
|
||||
let rootStat = null
|
||||
try {
|
||||
rootStat = await fsp.lstat(root)
|
||||
|
|
@ -117,11 +108,8 @@ async function treeSize(root) {
|
|||
return { files, bytes }
|
||||
}
|
||||
|
||||
// Copy a directory tree the way an imported game/wine build has to arrive:
|
||||
// symlinks recreated as they are (copyFile would silently drop them) and file
|
||||
// permissions carried over (copyFile writes 0644, killing scripts and any
|
||||
// binary the game executes itself). Reports cumulative { done, bytes } after
|
||||
// every file through `onProgress`, so long copies can drive a progress bar.
|
||||
// Copy a tree with symlinks recreated and permissions carried (copyFile
|
||||
// drops both); reports cumulative { done, bytes } through onProgress.
|
||||
async function copyTree(src, dst, onProgress) {
|
||||
let done = 0
|
||||
let bytes = 0
|
||||
|
|
@ -173,10 +161,8 @@ async function copyTree(src, dst, onProgress) {
|
|||
return { done, bytes }
|
||||
}
|
||||
|
||||
// Delete a tree deepest-first so a long removal (a multi-GB prefix) can drive
|
||||
// a progress bar instead of freezing the window on one rmSync. Symlinks are
|
||||
// unlinked, never followed. Reports cumulative { files, bytes, dirs } through
|
||||
// `onProgress`; a missing tree is simply done.
|
||||
// Delete deepest-first with progress through onProgress; symlinks are
|
||||
// unlinked, never followed.
|
||||
async function removeTree(root, onProgress) {
|
||||
let files = 0
|
||||
let dirs = 0
|
||||
|
|
@ -185,9 +171,7 @@ async function removeTree(root, onProgress) {
|
|||
const tick = () => {
|
||||
if (gate) gate({ files, dirs, bytes }, false)
|
||||
}
|
||||
// A symlink (or a file) as the root is removed as itself, never walked
|
||||
// through: the root of an import/prefix can be a link to another disk, and
|
||||
// deleting through it would take the target's files instead of the link.
|
||||
// a symlinked root is removed as itself, never walked through
|
||||
let rootStat = null
|
||||
try {
|
||||
rootStat = await fsp.lstat(root)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue