@vibe-agent-toolkit/utils 0.2.0-rc.10 → 0.2.0-rc.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -10
- package/dist/archive/archive.d.ts +129 -0
- package/dist/archive/archive.d.ts.map +1 -0
- package/dist/archive/archive.js +223 -0
- package/dist/archive/archive.js.map +1 -0
- package/dist/archive/entries.d.ts +132 -0
- package/dist/archive/entries.d.ts.map +1 -0
- package/dist/archive/entries.js +223 -0
- package/dist/archive/entries.js.map +1 -0
- package/dist/archive/limits.d.ts +39 -0
- package/dist/archive/limits.d.ts.map +1 -0
- package/dist/archive/limits.js +59 -0
- package/dist/archive/limits.js.map +1 -0
- package/dist/archive/records.d.ts +14 -0
- package/dist/archive/records.d.ts.map +1 -0
- package/dist/archive/records.js +3 -0
- package/dist/archive/records.js.map +1 -0
- package/dist/archive/tar-reader.d.ts +18 -0
- package/dist/archive/tar-reader.d.ts.map +1 -0
- package/dist/archive/tar-reader.js +173 -0
- package/dist/archive/tar-reader.js.map +1 -0
- package/dist/archive/zip-reader.d.ts +76 -0
- package/dist/archive/zip-reader.d.ts.map +1 -0
- package/dist/archive/zip-reader.js +376 -0
- package/dist/archive/zip-reader.js.map +1 -0
- package/dist/archive.d.ts +14 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/archive.js +12 -0
- package/dist/archive.js.map +1 -0
- package/dist/asset-reference.d.ts +17 -1
- package/dist/asset-reference.d.ts.map +1 -1
- package/dist/asset-reference.js +31 -7
- package/dist/asset-reference.js.map +1 -1
- package/dist/dirent-kind.d.ts +13 -40
- package/dist/dirent-kind.d.ts.map +1 -1
- package/dist/dirent-kind.js +21 -69
- package/dist/dirent-kind.js.map +1 -1
- package/dist/entrypoint.d.ts +2 -2
- package/dist/entrypoint.d.ts.map +1 -1
- package/dist/entrypoint.js +4 -3
- package/dist/entrypoint.js.map +1 -1
- package/dist/env-flag.d.ts +13 -5
- package/dist/env-flag.d.ts.map +1 -1
- package/dist/env-flag.js +13 -5
- package/dist/env-flag.js.map +1 -1
- package/dist/errors/confirmed-absent.d.ts +41 -0
- package/dist/errors/confirmed-absent.d.ts.map +1 -0
- package/dist/errors/confirmed-absent.js +43 -0
- package/dist/errors/confirmed-absent.js.map +1 -0
- package/dist/errors/errno-table.d.ts +177 -0
- package/dist/errors/errno-table.d.ts.map +1 -0
- package/dist/errors/errno-table.js +343 -0
- package/dist/errors/errno-table.js.map +1 -0
- package/dist/errors/fs-boundary.d.ts +36 -0
- package/dist/errors/fs-boundary.d.ts.map +1 -0
- package/dist/errors/fs-boundary.js +121 -0
- package/dist/errors/fs-boundary.js.map +1 -0
- package/dist/errors/fs-fault.d.ts +176 -0
- package/dist/errors/fs-fault.d.ts.map +1 -0
- package/dist/errors/fs-fault.js +215 -0
- package/dist/errors/fs-fault.js.map +1 -0
- package/dist/errors/git-errno.d.ts +13 -0
- package/dist/errors/git-errno.d.ts.map +1 -0
- package/dist/errors/git-errno.js +45 -0
- package/dist/errors/git-errno.js.map +1 -0
- package/dist/errors/path-present.d.ts +72 -0
- package/dist/errors/path-present.d.ts.map +1 -0
- package/dist/errors/path-present.js +110 -0
- package/dist/errors/path-present.js.map +1 -0
- package/dist/errors/rag-index-empty.d.ts +16 -0
- package/dist/errors/rag-index-empty.d.ts.map +1 -0
- package/dist/errors/rag-index-empty.js +16 -0
- package/dist/errors/rag-index-empty.js.map +1 -0
- package/dist/errors/suppressed-faults.d.ts +34 -0
- package/dist/errors/suppressed-faults.d.ts.map +1 -0
- package/dist/errors/suppressed-faults.js +66 -0
- package/dist/errors/suppressed-faults.js.map +1 -0
- package/dist/file-crawler.d.ts +13 -18
- package/dist/file-crawler.d.ts.map +1 -1
- package/dist/file-crawler.js +140 -24
- package/dist/file-crawler.js.map +1 -1
- package/dist/fs-utils.d.ts +75 -50
- package/dist/fs-utils.d.ts.map +1 -1
- package/dist/fs-utils.js +148 -158
- package/dist/fs-utils.js.map +1 -1
- package/dist/fs.d.ts +5 -4
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +5 -4
- package/dist/fs.js.map +1 -1
- package/dist/git-snapshot.d.ts +25 -17
- package/dist/git-snapshot.d.ts.map +1 -1
- package/dist/git-snapshot.js +65 -11
- package/dist/git-snapshot.js.map +1 -1
- package/dist/git-tracker.d.ts +11 -3
- package/dist/git-tracker.d.ts.map +1 -1
- package/dist/git-tracker.js +29 -6
- package/dist/git-tracker.js.map +1 -1
- package/dist/git-utils.d.ts.map +1 -1
- package/dist/git-utils.js +7 -35
- package/dist/git-utils.js.map +1 -1
- package/dist/git.d.ts +1 -1
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +1 -1
- package/dist/git.js.map +1 -1
- package/dist/gitignore-checker.d.ts.map +1 -1
- package/dist/gitignore-checker.js +5 -4
- package/dist/gitignore-checker.js.map +1 -1
- package/dist/in-order.d.ts +93 -0
- package/dist/in-order.d.ts.map +1 -0
- package/dist/in-order.js +165 -0
- package/dist/in-order.js.map +1 -0
- package/dist/index.d.ts +20 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -4
- package/dist/index.js.map +1 -1
- package/dist/kill-process-tree.d.ts +43 -0
- package/dist/kill-process-tree.d.ts.map +1 -0
- package/dist/kill-process-tree.js +48 -0
- package/dist/kill-process-tree.js.map +1 -0
- package/dist/link-following.d.ts +115 -0
- package/dist/link-following.d.ts.map +1 -0
- package/dist/link-following.js +283 -0
- package/dist/link-following.js.map +1 -0
- package/dist/listing-refusal.d.ts +44 -0
- package/dist/listing-refusal.d.ts.map +1 -1
- package/dist/listing-refusal.js +79 -2
- package/dist/listing-refusal.js.map +1 -1
- package/dist/name-fold.d.ts +25 -0
- package/dist/name-fold.d.ts.map +1 -0
- package/dist/name-fold.js +40 -0
- package/dist/name-fold.js.map +1 -0
- package/dist/path-containment.d.ts +17 -0
- package/dist/path-containment.d.ts.map +1 -1
- package/dist/path-containment.js +28 -5
- package/dist/path-containment.js.map +1 -1
- package/dist/path-utils.d.ts +14 -17
- package/dist/path-utils.d.ts.map +1 -1
- package/dist/path-utils.js +37 -55
- package/dist/path-utils.js.map +1 -1
- package/dist/process.d.ts +2 -0
- package/dist/process.d.ts.map +1 -1
- package/dist/process.js +2 -0
- package/dist/process.js.map +1 -1
- package/dist/project-utils.d.ts.map +1 -1
- package/dist/project-utils.js +8 -9
- package/dist/project-utils.js.map +1 -1
- package/dist/safe-exec.d.ts +6 -2
- package/dist/safe-exec.d.ts.map +1 -1
- package/dist/safe-exec.js +1 -1
- package/dist/safe-exec.js.map +1 -1
- package/dist/skill-targets.d.ts.map +1 -1
- package/dist/skill-targets.js +3 -1
- package/dist/skill-targets.js.map +1 -1
- package/dist/skill-test/spawn-claude.d.ts +0 -15
- package/dist/skill-test/spawn-claude.d.ts.map +1 -1
- package/dist/skill-test/spawn-claude.js +11 -50
- package/dist/skill-test/spawn-claude.js.map +1 -1
- package/dist/special-file.d.ts +18 -0
- package/dist/special-file.d.ts.map +1 -0
- package/dist/special-file.js +21 -0
- package/dist/special-file.js.map +1 -0
- package/dist/terminating-signals.d.ts +129 -0
- package/dist/terminating-signals.d.ts.map +1 -0
- package/dist/terminating-signals.js +210 -0
- package/dist/terminating-signals.js.map +1 -0
- package/dist/test-helpers.d.ts +9 -5
- package/dist/test-helpers.d.ts.map +1 -1
- package/dist/test-helpers.js +18 -21
- package/dist/test-helpers.js.map +1 -1
- package/dist/test-scratch-guard.d.ts +34 -0
- package/dist/test-scratch-guard.d.ts.map +1 -0
- package/dist/test-scratch-guard.js +45 -0
- package/dist/test-scratch-guard.js.map +1 -0
- package/dist/testing/archive-fixtures.d.ts +147 -0
- package/dist/testing/archive-fixtures.d.ts.map +1 -0
- package/dist/testing/archive-fixtures.js +449 -0
- package/dist/testing/archive-fixtures.js.map +1 -0
- package/dist/testing/executables.d.ts +6 -0
- package/dist/testing/executables.d.ts.map +1 -1
- package/dist/testing/executables.js +20 -9
- package/dist/testing/executables.js.map +1 -1
- package/dist/testing/fault-fs-preload.d.ts +16 -0
- package/dist/testing/fault-fs-preload.d.ts.map +1 -0
- package/dist/testing/fault-fs-preload.js +22 -0
- package/dist/testing/fault-fs-preload.js.map +1 -0
- package/dist/testing/fault-fs.d.ts +115 -0
- package/dist/testing/fault-fs.d.ts.map +1 -0
- package/dist/testing/fault-fs.js +411 -0
- package/dist/testing/fault-fs.js.map +1 -0
- package/dist/testing/fault-spec.d.ts +83 -0
- package/dist/testing/fault-spec.d.ts.map +1 -0
- package/dist/testing/fault-spec.js +132 -0
- package/dist/testing/fault-spec.js.map +1 -0
- package/dist/testing/hostile-tree.d.ts.map +1 -1
- package/dist/testing/hostile-tree.js +3 -4
- package/dist/testing/hostile-tree.js.map +1 -1
- package/dist/testing/platform-gates.d.ts +8 -0
- package/dist/testing/platform-gates.d.ts.map +1 -1
- package/dist/testing/platform-gates.js +24 -0
- package/dist/testing/platform-gates.js.map +1 -1
- package/dist/testing/temp-dir.d.ts +31 -0
- package/dist/testing/temp-dir.d.ts.map +1 -1
- package/dist/testing/temp-dir.js +63 -0
- package/dist/testing/temp-dir.js.map +1 -1
- package/dist/testing/tier-timeout.d.ts +34 -0
- package/dist/testing/tier-timeout.d.ts.map +1 -0
- package/dist/testing/tier-timeout.js +45 -0
- package/dist/testing/tier-timeout.js.map +1 -0
- package/dist/testing/tree-snapshot.d.ts +71 -0
- package/dist/testing/tree-snapshot.d.ts.map +1 -0
- package/dist/testing/tree-snapshot.js +163 -0
- package/dist/testing/tree-snapshot.js.map +1 -0
- package/dist/testing.d.ts +6 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +8 -1
- package/dist/testing.js.map +1 -1
- package/dist/text-content.d.ts +29 -0
- package/dist/text-content.d.ts.map +1 -1
- package/dist/text-content.js +64 -0
- package/dist/text-content.js.map +1 -1
- package/dist/text-file.d.ts +58 -6
- package/dist/text-file.d.ts.map +1 -1
- package/dist/text-file.js +111 -11
- package/dist/text-file.js.map +1 -1
- package/dist/text.d.ts +1 -1
- package/dist/text.d.ts.map +1 -1
- package/dist/text.js +1 -1
- package/dist/text.js.map +1 -1
- package/dist/timing-dump.d.ts.map +1 -1
- package/dist/timing-dump.js +2 -10
- package/dist/timing-dump.js.map +1 -1
- package/dist/tree-change/apply-decisions.d.ts +101 -0
- package/dist/tree-change/apply-decisions.d.ts.map +1 -0
- package/dist/tree-change/apply-decisions.js +139 -0
- package/dist/tree-change/apply-decisions.js.map +1 -0
- package/dist/tree-change/apply.d.ts +98 -0
- package/dist/tree-change/apply.d.ts.map +1 -0
- package/dist/tree-change/apply.js +364 -0
- package/dist/tree-change/apply.js.map +1 -0
- package/dist/tree-change/copy-decisions.d.ts +58 -0
- package/dist/tree-change/copy-decisions.d.ts.map +1 -0
- package/dist/tree-change/copy-decisions.js +66 -0
- package/dist/tree-change/copy-decisions.js.map +1 -0
- package/dist/tree-change/copy-tree.d.ts +125 -0
- package/dist/tree-change/copy-tree.d.ts.map +1 -0
- package/dist/tree-change/copy-tree.js +279 -0
- package/dist/tree-change/copy-tree.js.map +1 -0
- package/dist/tree-change/files.d.ts +167 -0
- package/dist/tree-change/files.d.ts.map +1 -0
- package/dist/tree-change/files.js +423 -0
- package/dist/tree-change/files.js.map +1 -0
- package/dist/tree-change/followed-walk.d.ts +54 -0
- package/dist/tree-change/followed-walk.d.ts.map +1 -0
- package/dist/tree-change/followed-walk.js +81 -0
- package/dist/tree-change/followed-walk.js.map +1 -0
- package/dist/tree-change/host-chain.d.ts +48 -0
- package/dist/tree-change/host-chain.d.ts.map +1 -0
- package/dist/tree-change/host-chain.js +85 -0
- package/dist/tree-change/host-chain.js.map +1 -0
- package/dist/tree-change/identity-compare.d.ts +61 -0
- package/dist/tree-change/identity-compare.d.ts.map +1 -0
- package/dist/tree-change/identity-compare.js +115 -0
- package/dist/tree-change/identity-compare.js.map +1 -0
- package/dist/tree-change/identity.d.ts +62 -0
- package/dist/tree-change/identity.d.ts.map +1 -0
- package/dist/tree-change/identity.js +152 -0
- package/dist/tree-change/identity.js.map +1 -0
- package/dist/tree-change/index.d.ts +24 -0
- package/dist/tree-change/index.d.ts.map +1 -0
- package/dist/tree-change/index.js +14 -0
- package/dist/tree-change/index.js.map +1 -0
- package/dist/tree-change/link-chain.d.ts +180 -0
- package/dist/tree-change/link-chain.d.ts.map +1 -0
- package/dist/tree-change/link-chain.js +377 -0
- package/dist/tree-change/link-chain.js.map +1 -0
- package/dist/tree-change/link-containment.d.ts +105 -0
- package/dist/tree-change/link-containment.d.ts.map +1 -0
- package/dist/tree-change/link-containment.js +196 -0
- package/dist/tree-change/link-containment.js.map +1 -0
- package/dist/tree-change/link-walk.d.ts +49 -0
- package/dist/tree-change/link-walk.d.ts.map +1 -0
- package/dist/tree-change/link-walk.js +69 -0
- package/dist/tree-change/link-walk.js.map +1 -0
- package/dist/tree-change/plan.d.ts +206 -0
- package/dist/tree-change/plan.d.ts.map +1 -0
- package/dist/tree-change/plan.js +320 -0
- package/dist/tree-change/plan.js.map +1 -0
- package/dist/tree-change/readable-tree.d.ts +44 -0
- package/dist/tree-change/readable-tree.d.ts.map +1 -0
- package/dist/tree-change/readable-tree.js +52 -0
- package/dist/tree-change/readable-tree.js.map +1 -0
- package/dist/tree-change/rollback-error.d.ts +29 -0
- package/dist/tree-change/rollback-error.d.ts.map +1 -0
- package/dist/tree-change/rollback-error.js +31 -0
- package/dist/tree-change/rollback-error.js.map +1 -0
- package/dist/tree-change/staging-names.d.ts +27 -0
- package/dist/tree-change/staging-names.d.ts.map +1 -0
- package/dist/tree-change/staging-names.js +40 -0
- package/dist/tree-change/staging-names.js.map +1 -0
- package/dist/tree-change/tree-walk.d.ts +81 -0
- package/dist/tree-change/tree-walk.d.ts.map +1 -0
- package/dist/tree-change/tree-walk.js +212 -0
- package/dist/tree-change/tree-walk.js.map +1 -0
- package/dist/win32-namespace.d.ts +24 -0
- package/dist/win32-namespace.d.ts.map +1 -0
- package/dist/win32-namespace.js +31 -0
- package/dist/win32-namespace.js.map +1 -0
- package/dist/yaml/surgical-yaml.d.ts +12 -3
- package/dist/yaml/surgical-yaml.d.ts.map +1 -1
- package/dist/yaml/surgical-yaml.js +16 -6
- package/dist/yaml/surgical-yaml.js.map +1 -1
- package/eslint/README.md +12 -4
- package/eslint/rules/fs-binding-scan.cjs +278 -0
- package/eslint/rules/no-adhoc-errno.cjs +364 -0
- package/eslint/rules/no-bare-symlink-in-tests.cjs +2 -3
- package/eslint/rules/no-blind-catch.cjs +1 -1
- package/eslint/rules/no-destructive-fs.cjs +359 -0
- package/eslint/rules/no-existssync.cjs +70 -0
- package/eslint/rules/no-fragile-entrypoint-guard.cjs +3 -2
- package/eslint/rules/no-link-following-fs.cjs +68 -0
- package/eslint/rules/no-literal-process-exit.cjs +96 -8
- package/eslint/rules/no-literal-test-timeout.cjs +214 -0
- package/eslint/rules/no-raw-signal-listener.cjs +224 -0
- package/eslint/rules/no-stdout-outside-writer.cjs +135 -0
- package/package.json +10 -2
- package/dist/errors/errno.d.ts +0 -51
- package/dist/errors/errno.d.ts.map +0 -1
- package/dist/errors/errno.js +0 -112
- package/dist/errors/errno.js.map +0 -1
- package/eslint/rules/no-fs-promises-cp.cjs +0 -43
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-tree.d.ts","sourceRoot":"","sources":["../../src/tree-change/copy-tree.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAKrE,OAAO,EAAgC,KAAK,QAAQ,EAAwE,MAAM,qBAAqB,CAAC;AACxJ,OAAO,EAAE,KAAK,gBAAgB,EAAqC,MAAM,YAAY,CAAC;AAEtF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAA8B,KAAK,WAAW,EAAY,MAAM,gBAAgB,CAAC;AAqDxF,mGAAmG;AACnG,UAAU,eAAe;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AA+BD,wHAAwH;AACxH,MAAM,WAAW,eAAgB,SAAQ,wBAAwB;IAC/D,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,WAAW,CAgE7G;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtH;AAED,mIAAmI;AACnI,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBpI"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `copyTree`: copy a directory tree by the same walk `proveTreeReadable` proves it
|
|
3
|
+
* with, reading each file from the very handle the walk judged a regular file.
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'node:fs/promises';
|
|
6
|
+
import { isAlreadyExistsError, isPathAbsentError } from '../errors/errno-table.js';
|
|
7
|
+
import { classifyFsFault } from '../errors/fs-fault.js';
|
|
8
|
+
import { linkCopyType } from '../link-following.js';
|
|
9
|
+
import { safePath } from '../path-core.js';
|
|
10
|
+
import { openForReading } from '../text-file.js';
|
|
11
|
+
import { aliasFault, foldedNameIsTwin, mayTakeOver, nameOf, parentOf, sameNameWhereFolded } from './copy-decisions.js';
|
|
12
|
+
import { makeDirectoryUnder, openFileUnder } from './files.js';
|
|
13
|
+
import { sameEntry } from './identity.js';
|
|
14
|
+
import { readingTree, treeReadFault, walkTree } from './tree-walk.js';
|
|
15
|
+
/** The owner's read, write and search bits, kept on every copied directory so its owner can always fill and remove it. */
|
|
16
|
+
const OWNER_RWX = 0o700;
|
|
17
|
+
/** The bytes of an open file being copied; a read failure is `readFault`'s. A write failure never reaches this catch: the writer's loop ends the generator with `return()`, not `throw()`. */
|
|
18
|
+
async function* sourceBytes(source, readFault) {
|
|
19
|
+
try {
|
|
20
|
+
yield* source.createReadStream({ autoClose: false, start: 0 });
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw readFault(error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Copy the bytes of an open file — one already judged a regular file on that very handle — into
|
|
28
|
+
* `claimed`, a file this copy has just made exclusively (opened `wx`), and carry its permission bits
|
|
29
|
+
* over, so a script stays executable — never its setuid, setgid or sticky bit. The ONE file copy of the tree copy and the
|
|
30
|
+
* single-file copy: bytes and mode both go to that very handle, never to a path, so nothing swapped
|
|
31
|
+
* in after the claim — a link least of all — is written or chmod-ed through. Closes `claimed`.
|
|
32
|
+
*/
|
|
33
|
+
async function copyOpenFileInto(handle, claimed, mode, readFault) {
|
|
34
|
+
try {
|
|
35
|
+
// On the handle, not through a stream of it: a stream owns the handle it writes and closes it
|
|
36
|
+
// with itself, before the mode could be set on it.
|
|
37
|
+
await claimed.writeFile(sourceBytes(handle, readFault));
|
|
38
|
+
// The permission bits only: setuid, setgid and sticky never travel with a copy.
|
|
39
|
+
await claimed.chmod(mode & 0o777);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
// The copy's own failure is the answer: a close refused after it is not a second one.
|
|
43
|
+
await claimed.close().catch(() => undefined);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
await claimed.close();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Make the root of a copy: with its parents when nothing is there, adopted when a real directory
|
|
50
|
+
* is. A link there — to a directory included — or a file is never adopted: the plain `mkdir` is the
|
|
51
|
+
* OS's own `EEXIST` for it, raw, as for any entry of a `fresh` destination.
|
|
52
|
+
*/
|
|
53
|
+
async function claimRoot(into) {
|
|
54
|
+
const there = await fs.lstat(into).catch((error) => {
|
|
55
|
+
if (isPathAbsentError(error))
|
|
56
|
+
return undefined;
|
|
57
|
+
throw error;
|
|
58
|
+
});
|
|
59
|
+
if (there === undefined)
|
|
60
|
+
await fs.mkdir(into, { recursive: true });
|
|
61
|
+
else if (!there.isDirectory())
|
|
62
|
+
await fs.mkdir(into);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Make the directory a copy goes into ({@link CopyDestination}): the root as the caller's, every
|
|
66
|
+
* component under it as a real directory or not at all.
|
|
67
|
+
*
|
|
68
|
+
* @param copied - What is copied, for a refusal's message
|
|
69
|
+
* @returns The directory's path
|
|
70
|
+
*/
|
|
71
|
+
async function claimDestination(into, copied) {
|
|
72
|
+
await claimRoot(into.root);
|
|
73
|
+
return into.relative === '' ? into.root : await makeDirectoryUnder(into.root, into.relative, `the copy of ${copied}`);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Make the directory a copy's own entry goes IN, for a source that is not a directory at all — a
|
|
77
|
+
* root that is a link, kept as one (`links: 'preserve'`): the destination root's parents as the
|
|
78
|
+
* caller's, every component under the root as a real directory or not at all.
|
|
79
|
+
*
|
|
80
|
+
* @param copied - What is copied, for a refusal's message
|
|
81
|
+
*/
|
|
82
|
+
async function claimParentOfDestination(into, copied) {
|
|
83
|
+
if (into.relative === '') {
|
|
84
|
+
await fs.mkdir(parentOf(into.root), { recursive: true });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
await claimRoot(into.root);
|
|
88
|
+
const parent = parentOf(into.relative);
|
|
89
|
+
if (parent !== '')
|
|
90
|
+
await makeDirectoryUnder(into.root, parent, `the copy of ${copied}`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The visitor that writes the copy of each entry the walk accepts under `dest`; every read of the
|
|
94
|
+
* copied tree is on `side`.
|
|
95
|
+
*
|
|
96
|
+
* Every create below the root is EXCLUSIVE and never follows a link: a file is opened `wx`, a
|
|
97
|
+
* directory made by a plain `mkdir`, a link made only where nothing is. So a create that finds
|
|
98
|
+
* something answers `EEXIST`, and what happens then is decided in this order:
|
|
99
|
+
*
|
|
100
|
+
* 1. The entry there is one THIS copy made — the same entry by identity, or (where the OS will not
|
|
101
|
+
* say) a sibling whose name is the same once case and Unicode form are folded: two source names,
|
|
102
|
+
* one destination name. Refused as the source's layout (`aliasFault`), under either mode.
|
|
103
|
+
* 2. `fresh`: refused as it is (`EEXIST`), for the caller's boundary to classify.
|
|
104
|
+
* 3. `merge`: a real directory is adopted; a file or a link is removed (the link, never its target)
|
|
105
|
+
* and the entry made anew; anything else — a directory where a file goes, a link where a
|
|
106
|
+
* directory goes — is refused as it is (`mayTakeOver`).
|
|
107
|
+
*
|
|
108
|
+
* Where the copy goes is made by {@link claimDestination}: the root is the caller's (made with its
|
|
109
|
+
* parents when absent, adopted when a real directory, refused `EEXIST` when a link or a file — a link
|
|
110
|
+
* taken for it would put the whole copy where it points), and every directory from the root down to
|
|
111
|
+
* the copy is a real one or is refused as the layout of the tree it is in.
|
|
112
|
+
*
|
|
113
|
+
* Exported for `copyTree` and for the suite that hands it two entries by name — a real alias needs
|
|
114
|
+
* a case-sensitive source and a case-folding destination, which no one temp directory offers.
|
|
115
|
+
*/
|
|
116
|
+
export function copyVisitor(where, copied, side, onto) {
|
|
117
|
+
const dest = where.relative === '' ? where.root : safePath.join(where.root, where.relative);
|
|
118
|
+
const target = (relative) => (relative === '' ? dest : safePath.join(dest, relative));
|
|
119
|
+
/** What this copy made, by the directory (relative to the root) it made it in. */
|
|
120
|
+
const made = new Map();
|
|
121
|
+
const madeIn = (parent) => {
|
|
122
|
+
const list = made.get(parent) ?? [];
|
|
123
|
+
made.set(parent, list);
|
|
124
|
+
return list;
|
|
125
|
+
};
|
|
126
|
+
const twinOf = async (entry, into) => {
|
|
127
|
+
const siblings = madeIn(parentOf(entry.relative));
|
|
128
|
+
const byIdentity = siblings.find((each) => sameEntry(target(each.relative), into) === 'same');
|
|
129
|
+
if (byIdentity !== undefined)
|
|
130
|
+
return byIdentity;
|
|
131
|
+
const byName = siblings.find((each) => sameNameWhereFolded(nameOf(each.relative), nameOf(entry.relative)));
|
|
132
|
+
if (byName === undefined)
|
|
133
|
+
return undefined;
|
|
134
|
+
// Absent or unexaminable alike: then the collision is all there is to go on, and the name decides.
|
|
135
|
+
const present = await fs.lstat(into).then(() => true, () => false);
|
|
136
|
+
return foldedNameIsTwin(sameEntry(target(byName.relative), into), present) ? byName : undefined;
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Claim `entry`'s place by `claim` — an exclusive create, and nothing else, so it can be asked
|
|
140
|
+
* twice — and hand back what it made (`undefined`: a directory a merge adopted).
|
|
141
|
+
*/
|
|
142
|
+
const create = async (entry, kind, claim) => {
|
|
143
|
+
const into = target(entry.relative);
|
|
144
|
+
const claimed = await claim(into).catch(async (error) => {
|
|
145
|
+
if (!isAlreadyExistsError(error))
|
|
146
|
+
throw error;
|
|
147
|
+
const twin = await twinOf(entry, into);
|
|
148
|
+
if (twin !== undefined)
|
|
149
|
+
throw aliasFault(twin, entry, error);
|
|
150
|
+
const takeOver = mayTakeOver(onto, kind, onto === 'merge' ? (await fs.lstat(into)).isDirectory() : false);
|
|
151
|
+
if (takeOver === 'refuse')
|
|
152
|
+
throw error;
|
|
153
|
+
if (takeOver === 'adopt')
|
|
154
|
+
return undefined;
|
|
155
|
+
await fs.unlink(into);
|
|
156
|
+
return claim(into);
|
|
157
|
+
});
|
|
158
|
+
madeIn(parentOf(entry.relative)).push(entry);
|
|
159
|
+
return claimed;
|
|
160
|
+
};
|
|
161
|
+
return {
|
|
162
|
+
async directory(entry, stats) {
|
|
163
|
+
const into = target(entry.relative);
|
|
164
|
+
if (entry.relative === '')
|
|
165
|
+
await claimDestination(where, copied);
|
|
166
|
+
else
|
|
167
|
+
await create(entry, 'directory', (path) => fs.mkdir(path));
|
|
168
|
+
await fs.chmod(into, (stats.mode & 0o7777) | OWNER_RWX);
|
|
169
|
+
},
|
|
170
|
+
async file(entry, handle, stats) {
|
|
171
|
+
const claimed = await create(entry, 'leaf', (into) => fs.open(into, 'wx'));
|
|
172
|
+
if (claimed !== undefined)
|
|
173
|
+
await copyOpenFileInto(handle, claimed, stats.mode, (error) => treeReadFault(side, entry.path, error));
|
|
174
|
+
},
|
|
175
|
+
async link(entry) {
|
|
176
|
+
const linkTarget = await readingTree(side, entry.path, () => fs.readlink(entry.path));
|
|
177
|
+
// Typed from the chain read by its text, before anything is made: an untyped `symlink` has
|
|
178
|
+
// Node on Windows ask the kernel to follow the target to pick `file` or `dir`, so a network or
|
|
179
|
+
// device text — at any hop — is refused here, on the copied tree's side, never handed on.
|
|
180
|
+
const type = await readingTree(side, entry.path, () => Promise.resolve().then(() => linkCopyType(entry.path, copied)));
|
|
181
|
+
// The source itself is a link: there is no copied directory to hold it, so its place is made first.
|
|
182
|
+
if (entry.relative === '')
|
|
183
|
+
await claimParentOfDestination(where, copied);
|
|
184
|
+
// Verbatim. A host that cannot make the link (Windows without the privilege: EPERM; a
|
|
185
|
+
// filesystem with none: ENOTSUP) raises the raw errno, a write like any other, for the
|
|
186
|
+
// caller's boundary to classify.
|
|
187
|
+
await create(entry, 'leaf', (into) => fs.symlink(linkTarget, into, type));
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Copy the directory `source` to `relative` under `root` ({@link CopyDestination}).
|
|
193
|
+
*
|
|
194
|
+
* `root` is a directory the caller made or its user named: created, with its parents, when absent;
|
|
195
|
+
* adopted when a real directory; refused, `EEXIST`, when a link or a file stands there. `relative`
|
|
196
|
+
* is `''` for a copy onto `root` itself. A copy that goes INSIDE a tree — a pool skill into a staged
|
|
197
|
+
* plugin that earlier copies filled, links kept — names that tree's root and where under it, and
|
|
198
|
+
* every directory between the two must then be a real one (made when absent): a link or a file
|
|
199
|
+
* there is a `source` fault (origin `content`, class `occupied`) naming it, never followed. So a
|
|
200
|
+
* caller cannot reach through a link by how deep its destination is: the only directory taken on
|
|
201
|
+
* trust is the one it declares as `root`.
|
|
202
|
+
*
|
|
203
|
+
* Entries are walked, and refused, exactly as `proveTreeReadable` proves them (see
|
|
204
|
+
* `tree-walk.ts`): a `follow-contained` link is copied as what it points at, inside
|
|
205
|
+
* the source only; a `preserve` link is copied as a link, its target string
|
|
206
|
+
* verbatim and never followed — its chain is read by text alone to give the copy its `file`/`dir`
|
|
207
|
+
* type, and one through a network or device path is refused (a `refused` fault on `options.side`)
|
|
208
|
+
* before anything is made; an entry `filter` excludes is never touched; a named
|
|
209
|
+
* pipe, socket or device is refused unopened. Each file is copied from the handle
|
|
210
|
+
* `fstat` judged, with its mode. Each directory takes its source's mode with the
|
|
211
|
+
* owner's rwx kept (`| 0o700`): a read-only source must not become a copy nothing
|
|
212
|
+
* can fill or remove.
|
|
213
|
+
*
|
|
214
|
+
* Below the copy's own directory nothing already there is ever adopted or written through, and two source
|
|
215
|
+
* entries that are one name there are refused as the source's layout (a `source` fault
|
|
216
|
+
* naming both): see {@link copyVisitor} and `options.onto`.
|
|
217
|
+
*
|
|
218
|
+
* The copy names no side for what it WRITES: a failure writing the copy is the raw
|
|
219
|
+
* errno, for the caller's boundary to classify — a link this host cannot create, and an
|
|
220
|
+
* `EEXIST` for something already at a name of a `fresh` destination, included. What it READS is on the side the caller names, as the proof's reads
|
|
221
|
+
* are: a refusal is a classified fault on `options.side` (origin `content`) naming
|
|
222
|
+
* the entry. Only the caller knows whether the tree is an input (`source`), VAT's
|
|
223
|
+
* staging (`environment`) or a copy already made into user state (`destination`).
|
|
224
|
+
*
|
|
225
|
+
* @param source - The directory to copy
|
|
226
|
+
* @param root - The directory the caller made or owns, which the copy goes into or under
|
|
227
|
+
* @param relative - Where under `root` the copy goes, forward slashes; `''` for `root` itself
|
|
228
|
+
* @param options - `links`, `filter` and `side`, exactly as `proveTreeReadable` was given them, and `onto`
|
|
229
|
+
*/
|
|
230
|
+
export async function copyTree(source, root, relative, options) {
|
|
231
|
+
await walkTree(source, options, options.side, copyVisitor({ root, relative }, source, options.side, options.onto));
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Copy ONE regular file to `relative` under `root`, as {@link copyTree} copies a file: opened
|
|
235
|
+
* without blocking and judged by `fstat` on that handle (a named pipe, socket or device is refused
|
|
236
|
+
* before a byte is read, never waited on), its bytes copied from that very handle, its mode
|
|
237
|
+
* carried over.
|
|
238
|
+
*
|
|
239
|
+
* The copy is made as `writeFileUnder` makes a file — it is the same primitive: every directory of
|
|
240
|
+
* `relative` must be a real directory (made by a plain `mkdir` when absent), the file is created
|
|
241
|
+
* exclusively, and its bytes and mode go to that handle. So it never writes through a link, at the
|
|
242
|
+
* file's name or on the way to it; `options.existing` decides a regular file already there.
|
|
243
|
+
*
|
|
244
|
+
* Every read is a classified fault on `options.side` (origin `content`), naming what was read. An
|
|
245
|
+
* entry in the copy's way is a `source` fault (origin `content`, class `occupied`) naming it; any
|
|
246
|
+
* other failure writing is the raw errno, for the caller's boundary to classify.
|
|
247
|
+
*
|
|
248
|
+
* @param source - The file to copy
|
|
249
|
+
* @param root - The root of the tree the copy goes into, which the caller made
|
|
250
|
+
* @param relative - Where the copy goes, relative to `root`, forward slashes
|
|
251
|
+
* @param options - The side `source` is on and what it is; `existing` and `writing`, for the copy
|
|
252
|
+
*/
|
|
253
|
+
export async function copyRegularFile(source, root, relative, options) {
|
|
254
|
+
// Every read — the open, the `fstat`, the stream, the close — names what was read, on its side.
|
|
255
|
+
const readFault = (error) => classifyFsFault(error, { side: options.side, origin: 'content', action: `read ${options.reading}`, path: source });
|
|
256
|
+
const reading = async (read) => {
|
|
257
|
+
try {
|
|
258
|
+
return await read();
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
throw readFault(error);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
const handle = await reading(() => openForReading(source));
|
|
265
|
+
try {
|
|
266
|
+
const stats = await reading(() => handle.stat());
|
|
267
|
+
// Only once the source is open and judged: a `replace` removes nothing for a copy that cannot be read.
|
|
268
|
+
const claimed = await openFileUnder(root, relative, options);
|
|
269
|
+
await copyOpenFileInto(handle, claimed, stats.mode, readFault);
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
// The copy's own failure is the answer: a close refused after it is not a second one.
|
|
273
|
+
await handle.close().catch(() => undefined);
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
// The close is a read of the source, too: a refusal of it is on the source's side.
|
|
277
|
+
await reading(() => handle.close());
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=copy-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-tree.js","sourceRoot":"","sources":["../../src/tree-change/copy-tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The file-level half of the tree-change primitive: the staging names every
|
|
3
|
+
* change sits beside its destination under, the one rename (retried where Windows
|
|
4
|
+
* makes a rename race a scanner), the one removal (a read-only tree included), a
|
|
5
|
+
* whole-file replace that never truncates what it replaces, and a temp directory
|
|
6
|
+
* that is always disposed of.
|
|
7
|
+
*/
|
|
8
|
+
import { type FileHandle } from 'node:fs/promises';
|
|
9
|
+
export { TEMP_DIR_OUTSIDE_TMPDIR_CODE } from './apply-decisions.js';
|
|
10
|
+
/**
|
|
11
|
+
* Rename `from` to `to` — a file or a whole tree — in one step. Under win32 a
|
|
12
|
+
* rename the OS refuses with contention (`EPERM`, `EBUSY`, `EACCES`: a scanner,
|
|
13
|
+
* an indexer, a handle still closing) is retried, up to 6 tries with a backoff of
|
|
14
|
+
* 50·2ⁿ ms (1.55 s in all); any other errno, and any errno on another platform,
|
|
15
|
+
* is final.
|
|
16
|
+
*
|
|
17
|
+
* @param from - The entry to move
|
|
18
|
+
* @param to - Its new name, on the same filesystem
|
|
19
|
+
* @throws the rename's raw errno, for the caller to classify on the side it knows
|
|
20
|
+
*/
|
|
21
|
+
export declare function renameFileAtomic(from: string, to: string): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Remove `entry` — a tree, a file or a link (never what it points at) — whatever
|
|
24
|
+
* the modes under it: the root gets the owner's rwx first, and a removal still
|
|
25
|
+
* refused (`EACCES` / `EPERM`: a read-only directory deeper down refuses the
|
|
26
|
+
* removal of its entries) is retried once every directory under it has been given
|
|
27
|
+
* them too. Nothing there is not a failure. A root the OS will not chmod is still
|
|
28
|
+
* removed when the removal itself is allowed. Done means not there: a removal that
|
|
29
|
+
* resolved with the entry still present (`rm`'s `force` reading its own listing's
|
|
30
|
+
* ENOENT as "gone") is run once more, and a plain `rmdir` then throws why it stays.
|
|
31
|
+
*
|
|
32
|
+
* @throws the raw errno of the chmod, listing or removal that failed
|
|
33
|
+
*/
|
|
34
|
+
export declare function removeEntry(entry: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Replace the file `dest` with `contents` in one step: the bytes go to a temp
|
|
37
|
+
* name beside it, which is then renamed over it ({@link renameFileAtomic}). A
|
|
38
|
+
* write that fails — a full disk mid-write — leaves `dest` byte-equal and the
|
|
39
|
+
* temp removed (a temp that will not go is recorded beside the thrown error:
|
|
40
|
+
* `suppressedFaultsOf`). An existing file keeps its mode, and must be writable as it is: one
|
|
41
|
+
* a write in place would be refused (a read-only file) is refused before anything is written,
|
|
42
|
+
* never replaced by the rename. A link is written through, so it stays a link to the replaced file.
|
|
43
|
+
*
|
|
44
|
+
* @param dest - The file to replace or create
|
|
45
|
+
* @param contents - Its new bytes
|
|
46
|
+
* @throws the raw errno, for the caller to classify on the side it knows
|
|
47
|
+
*/
|
|
48
|
+
export declare function replaceFile(dest: string, contents: string | Uint8Array): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Make the directory `relative` under `root` — a tree VAT is building, which may hold whatever its
|
|
51
|
+
* source shipped, links included — without ever going through a link: every component must be a real
|
|
52
|
+
* directory (adopted when there, made by a plain `mkdir` when absent). What a recursive `mkdir`
|
|
53
|
+
* would do instead is follow a link standing where a component goes, out of the tree.
|
|
54
|
+
*
|
|
55
|
+
* @param root - The tree's root, which the caller made
|
|
56
|
+
* @param relative - The directory, relative to `root`, forward slashes
|
|
57
|
+
* @param writing - What the directory is for, for a refusal's message
|
|
58
|
+
* @returns The directory's path
|
|
59
|
+
* @throws FsFaultError side `source`, origin `content`, class `occupied`, naming the link or file
|
|
60
|
+
* standing where a directory goes; any other failure is the raw errno
|
|
61
|
+
*/
|
|
62
|
+
export declare function makeDirectoryUnder(root: string, relative: string, writing: string): Promise<string>;
|
|
63
|
+
/** What decides the entry already AT the name of a file VAT makes under a tree, and what a refusal calls the file. */
|
|
64
|
+
export interface FileUnderOptions {
|
|
65
|
+
/**
|
|
66
|
+
* - `refuse`: anything there refuses the file.
|
|
67
|
+
* - `replace`: a regular file there is removed first (VAT's own earlier output, or a file the source
|
|
68
|
+
* shipped that VAT's supersedes); a link or a directory still refuses.
|
|
69
|
+
*/
|
|
70
|
+
readonly existing: 'refuse' | 'replace';
|
|
71
|
+
/** What the file is, for a refusal's message. */
|
|
72
|
+
readonly writing: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Write a file VAT makes into a tree it is building, never over or through what is already there
|
|
76
|
+
* (see {@link createUnder}: real directories only, an exclusive create, `existing` deciding the
|
|
77
|
+
* entry at the file's own name).
|
|
78
|
+
*
|
|
79
|
+
* @param root - The tree's root, which the caller made
|
|
80
|
+
* @param relative - The file, relative to `root`, forward slashes
|
|
81
|
+
* @param contents - Its bytes
|
|
82
|
+
* @param options - `existing`, and `writing`: what the file is, for a refusal's message
|
|
83
|
+
* @throws FsFaultError side `source`, origin `content`, class `occupied`, naming the entry in the
|
|
84
|
+
* way; any other failure is the raw errno, for the caller's boundary to classify
|
|
85
|
+
*/
|
|
86
|
+
export declare function writeFileUnder(root: string, relative: string, contents: string | Uint8Array, options: FileUnderOptions): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* {@link writeFileUnder} for bytes that are streamed: the file is made the same way and handed back
|
|
89
|
+
* OPEN, for the caller to fill and close. What the copy of one file into such a tree is built on.
|
|
90
|
+
*
|
|
91
|
+
* @returns The new file's handle, open for writing; the caller closes it
|
|
92
|
+
*/
|
|
93
|
+
export declare function openFileUnder(root: string, relative: string, options: FileUnderOptions): Promise<FileHandle>;
|
|
94
|
+
/**
|
|
95
|
+
* Remove a temporary directory, its modes notwithstanding — only one strictly
|
|
96
|
+
* under the temp directory (`normalizedTmpdir()`): this removal makes a read-only
|
|
97
|
+
* tree writable before it deletes it, so a wrong argument (an empty string, a
|
|
98
|
+
* project directory) must be refused before anything is touched. A directory
|
|
99
|
+
* elsewhere that VAT owns goes through a `remove` plan.
|
|
100
|
+
*
|
|
101
|
+
* @param dir - The directory
|
|
102
|
+
* @returns `undefined` when it is gone (or was never there); otherwise the leftover: the
|
|
103
|
+
* classified fault (an `FsFaultError`, side `environment`) whose message names the directory,
|
|
104
|
+
* for the caller to report as the one `TREE_CLEANUP_INCOMPLETE` warning beside its work
|
|
105
|
+
* @throws VatError {@link TEMP_DIR_OUTSIDE_TMPDIR_CODE} — a defect in the caller — for a
|
|
106
|
+
* directory not strictly under the temp directory, with nothing removed
|
|
107
|
+
*/
|
|
108
|
+
export declare function disposeTempDir(dir: string): Promise<unknown>;
|
|
109
|
+
/**
|
|
110
|
+
* {@link disposeTempDir}, synchronously — for a process on its way OUT, where no promise will ever
|
|
111
|
+
* settle: a signal handler about to re-raise, an `exit` listener. Same refusal of any directory not
|
|
112
|
+
* strictly under the temp directory, same answer.
|
|
113
|
+
*
|
|
114
|
+
* ⚠️ No mode repair: it is for a directory the process filled with its own ordinary files. A
|
|
115
|
+
* SHORT bounded retry ({@link SYNC_DISPOSAL_RETRIES} × {@link SYNC_DISPOSAL_RETRY_DELAY_MS}, linear
|
|
116
|
+
* backoff, at most ~0.4 s) covers the one transient refusal a dying process meets: on Windows a
|
|
117
|
+
* child it has just terminated still holds a handle in the directory for a moment, and removal
|
|
118
|
+
* answers `EBUSY`/`EPERM` until the OS lets go. Anything still there after it is answered as the
|
|
119
|
+
* leftover fault.
|
|
120
|
+
*
|
|
121
|
+
* @param dir - The directory
|
|
122
|
+
* @returns `undefined` when it is gone (or was never there); otherwise the leftover fault
|
|
123
|
+
* @throws VatError {@link TEMP_DIR_OUTSIDE_TMPDIR_CODE} — a defect in the caller — for a
|
|
124
|
+
* directory not strictly under the temp directory, with nothing removed
|
|
125
|
+
*/
|
|
126
|
+
export declare function disposeTempDirSync(dir: string): unknown;
|
|
127
|
+
/**
|
|
128
|
+
* Dispose of a temporary directory because the work that owned it failed — for a directory
|
|
129
|
+
* whose lifetime is not one call (one handed back to the caller on success, removed only on
|
|
130
|
+
* failure), where {@link withTempDir} cannot hold it. The failure stays the answer: a
|
|
131
|
+
* disposal fault is recorded beside it (`suppressedFaultsOf`), never thrown in its place.
|
|
132
|
+
*
|
|
133
|
+
* @param dir - The directory, strictly under the temp directory
|
|
134
|
+
* @param failure - What the work threw; the caller rethrows it
|
|
135
|
+
* @returns `undefined` when the directory went; otherwise the leftover fault, already recorded
|
|
136
|
+
* beside `failure` — for a caller that must also say so where no report will carry the failure
|
|
137
|
+
* @throws VatError {@link TEMP_DIR_OUTSIDE_TMPDIR_CODE} — a defect in the caller — for a
|
|
138
|
+
* directory not strictly under the temp directory, with nothing removed
|
|
139
|
+
*/
|
|
140
|
+
export declare function disposeTempDirAfterFailure(dir: string, failure: unknown): Promise<unknown>;
|
|
141
|
+
/** What {@link withTempDir} hands back once its work SUCCEEDED: the work's value, and what the disposal left. */
|
|
142
|
+
export interface TempDirOutcome<T> {
|
|
143
|
+
/** What `work` returned. */
|
|
144
|
+
readonly value: T;
|
|
145
|
+
/**
|
|
146
|
+
* `undefined` when the directory went; otherwise the classified fault (an `FsFaultError`, side
|
|
147
|
+
* `environment`, its message naming the directory) of a directory the OS would not remove. The
|
|
148
|
+
* work is DONE: this is never its refusal, but the one `TREE_CLEANUP_INCOMPLETE` warning a verb
|
|
149
|
+
* reports beside the work it finished.
|
|
150
|
+
*/
|
|
151
|
+
readonly leftover: unknown;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Run `work` in a fresh directory under the temp dir (`normalizedTmpdir()`), and
|
|
155
|
+
* dispose of it after, whatever happened.
|
|
156
|
+
*
|
|
157
|
+
* The work's error always wins: rethrown unchanged — never wrapped, never given a
|
|
158
|
+
* cause, never mutated — with a disposal failure recorded beside it
|
|
159
|
+
* (`suppressedFaultsOf`), so a report still names the directory left behind.
|
|
160
|
+
* When the work succeeded, nothing is thrown: the value comes back with the
|
|
161
|
+
* disposal's `leftover` (see {@link TempDirOutcome}), for the caller to report.
|
|
162
|
+
*
|
|
163
|
+
* @param prefix - `mkdtemp` prefix, so a leaked directory names its owner
|
|
164
|
+
* @param work - Given the directory's forward-slash path
|
|
165
|
+
*/
|
|
166
|
+
export declare function withTempDir<T>(prefix: string, work: (dir: string) => Promise<T>): Promise<TempDirOutcome<T>>;
|
|
167
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/tree-change/files.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAW,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAmBvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAWpE;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExE;AA4BD;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9D;AA+DD;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB5F;AAkCD;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEzG;AAED,sHAAsH;AACtH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IACxC,iDAAiD;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AA6BD;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5I;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAE5G;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGlE;AAOD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQvD;AASD;;;;;;;;;;;;GAYG;AACH,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAKhG;AAED,iHAAiH;AACjH,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAWlH"}
|