@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.
Files changed (330) hide show
  1. package/README.md +112 -10
  2. package/dist/archive/archive.d.ts +129 -0
  3. package/dist/archive/archive.d.ts.map +1 -0
  4. package/dist/archive/archive.js +223 -0
  5. package/dist/archive/archive.js.map +1 -0
  6. package/dist/archive/entries.d.ts +132 -0
  7. package/dist/archive/entries.d.ts.map +1 -0
  8. package/dist/archive/entries.js +223 -0
  9. package/dist/archive/entries.js.map +1 -0
  10. package/dist/archive/limits.d.ts +39 -0
  11. package/dist/archive/limits.d.ts.map +1 -0
  12. package/dist/archive/limits.js +59 -0
  13. package/dist/archive/limits.js.map +1 -0
  14. package/dist/archive/records.d.ts +14 -0
  15. package/dist/archive/records.d.ts.map +1 -0
  16. package/dist/archive/records.js +3 -0
  17. package/dist/archive/records.js.map +1 -0
  18. package/dist/archive/tar-reader.d.ts +18 -0
  19. package/dist/archive/tar-reader.d.ts.map +1 -0
  20. package/dist/archive/tar-reader.js +173 -0
  21. package/dist/archive/tar-reader.js.map +1 -0
  22. package/dist/archive/zip-reader.d.ts +76 -0
  23. package/dist/archive/zip-reader.d.ts.map +1 -0
  24. package/dist/archive/zip-reader.js +376 -0
  25. package/dist/archive/zip-reader.js.map +1 -0
  26. package/dist/archive.d.ts +14 -0
  27. package/dist/archive.d.ts.map +1 -0
  28. package/dist/archive.js +12 -0
  29. package/dist/archive.js.map +1 -0
  30. package/dist/asset-reference.d.ts +17 -1
  31. package/dist/asset-reference.d.ts.map +1 -1
  32. package/dist/asset-reference.js +31 -7
  33. package/dist/asset-reference.js.map +1 -1
  34. package/dist/dirent-kind.d.ts +13 -40
  35. package/dist/dirent-kind.d.ts.map +1 -1
  36. package/dist/dirent-kind.js +21 -69
  37. package/dist/dirent-kind.js.map +1 -1
  38. package/dist/entrypoint.d.ts +2 -2
  39. package/dist/entrypoint.d.ts.map +1 -1
  40. package/dist/entrypoint.js +4 -3
  41. package/dist/entrypoint.js.map +1 -1
  42. package/dist/env-flag.d.ts +13 -5
  43. package/dist/env-flag.d.ts.map +1 -1
  44. package/dist/env-flag.js +13 -5
  45. package/dist/env-flag.js.map +1 -1
  46. package/dist/errors/confirmed-absent.d.ts +41 -0
  47. package/dist/errors/confirmed-absent.d.ts.map +1 -0
  48. package/dist/errors/confirmed-absent.js +43 -0
  49. package/dist/errors/confirmed-absent.js.map +1 -0
  50. package/dist/errors/errno-table.d.ts +177 -0
  51. package/dist/errors/errno-table.d.ts.map +1 -0
  52. package/dist/errors/errno-table.js +343 -0
  53. package/dist/errors/errno-table.js.map +1 -0
  54. package/dist/errors/fs-boundary.d.ts +36 -0
  55. package/dist/errors/fs-boundary.d.ts.map +1 -0
  56. package/dist/errors/fs-boundary.js +121 -0
  57. package/dist/errors/fs-boundary.js.map +1 -0
  58. package/dist/errors/fs-fault.d.ts +176 -0
  59. package/dist/errors/fs-fault.d.ts.map +1 -0
  60. package/dist/errors/fs-fault.js +215 -0
  61. package/dist/errors/fs-fault.js.map +1 -0
  62. package/dist/errors/git-errno.d.ts +13 -0
  63. package/dist/errors/git-errno.d.ts.map +1 -0
  64. package/dist/errors/git-errno.js +45 -0
  65. package/dist/errors/git-errno.js.map +1 -0
  66. package/dist/errors/path-present.d.ts +72 -0
  67. package/dist/errors/path-present.d.ts.map +1 -0
  68. package/dist/errors/path-present.js +110 -0
  69. package/dist/errors/path-present.js.map +1 -0
  70. package/dist/errors/rag-index-empty.d.ts +16 -0
  71. package/dist/errors/rag-index-empty.d.ts.map +1 -0
  72. package/dist/errors/rag-index-empty.js +16 -0
  73. package/dist/errors/rag-index-empty.js.map +1 -0
  74. package/dist/errors/suppressed-faults.d.ts +34 -0
  75. package/dist/errors/suppressed-faults.d.ts.map +1 -0
  76. package/dist/errors/suppressed-faults.js +66 -0
  77. package/dist/errors/suppressed-faults.js.map +1 -0
  78. package/dist/file-crawler.d.ts +13 -18
  79. package/dist/file-crawler.d.ts.map +1 -1
  80. package/dist/file-crawler.js +140 -24
  81. package/dist/file-crawler.js.map +1 -1
  82. package/dist/fs-utils.d.ts +75 -50
  83. package/dist/fs-utils.d.ts.map +1 -1
  84. package/dist/fs-utils.js +148 -158
  85. package/dist/fs-utils.js.map +1 -1
  86. package/dist/fs.d.ts +5 -4
  87. package/dist/fs.d.ts.map +1 -1
  88. package/dist/fs.js +5 -4
  89. package/dist/fs.js.map +1 -1
  90. package/dist/git-snapshot.d.ts +25 -17
  91. package/dist/git-snapshot.d.ts.map +1 -1
  92. package/dist/git-snapshot.js +65 -11
  93. package/dist/git-snapshot.js.map +1 -1
  94. package/dist/git-tracker.d.ts +11 -3
  95. package/dist/git-tracker.d.ts.map +1 -1
  96. package/dist/git-tracker.js +29 -6
  97. package/dist/git-tracker.js.map +1 -1
  98. package/dist/git-utils.d.ts.map +1 -1
  99. package/dist/git-utils.js +7 -35
  100. package/dist/git-utils.js.map +1 -1
  101. package/dist/git.d.ts +1 -1
  102. package/dist/git.d.ts.map +1 -1
  103. package/dist/git.js +1 -1
  104. package/dist/git.js.map +1 -1
  105. package/dist/gitignore-checker.d.ts.map +1 -1
  106. package/dist/gitignore-checker.js +5 -4
  107. package/dist/gitignore-checker.js.map +1 -1
  108. package/dist/in-order.d.ts +93 -0
  109. package/dist/in-order.d.ts.map +1 -0
  110. package/dist/in-order.js +165 -0
  111. package/dist/in-order.js.map +1 -0
  112. package/dist/index.d.ts +20 -4
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.js +30 -4
  115. package/dist/index.js.map +1 -1
  116. package/dist/kill-process-tree.d.ts +43 -0
  117. package/dist/kill-process-tree.d.ts.map +1 -0
  118. package/dist/kill-process-tree.js +48 -0
  119. package/dist/kill-process-tree.js.map +1 -0
  120. package/dist/link-following.d.ts +115 -0
  121. package/dist/link-following.d.ts.map +1 -0
  122. package/dist/link-following.js +283 -0
  123. package/dist/link-following.js.map +1 -0
  124. package/dist/listing-refusal.d.ts +44 -0
  125. package/dist/listing-refusal.d.ts.map +1 -1
  126. package/dist/listing-refusal.js +79 -2
  127. package/dist/listing-refusal.js.map +1 -1
  128. package/dist/name-fold.d.ts +25 -0
  129. package/dist/name-fold.d.ts.map +1 -0
  130. package/dist/name-fold.js +40 -0
  131. package/dist/name-fold.js.map +1 -0
  132. package/dist/path-containment.d.ts +17 -0
  133. package/dist/path-containment.d.ts.map +1 -1
  134. package/dist/path-containment.js +28 -5
  135. package/dist/path-containment.js.map +1 -1
  136. package/dist/path-utils.d.ts +14 -17
  137. package/dist/path-utils.d.ts.map +1 -1
  138. package/dist/path-utils.js +37 -55
  139. package/dist/path-utils.js.map +1 -1
  140. package/dist/process.d.ts +2 -0
  141. package/dist/process.d.ts.map +1 -1
  142. package/dist/process.js +2 -0
  143. package/dist/process.js.map +1 -1
  144. package/dist/project-utils.d.ts.map +1 -1
  145. package/dist/project-utils.js +8 -9
  146. package/dist/project-utils.js.map +1 -1
  147. package/dist/safe-exec.d.ts +6 -2
  148. package/dist/safe-exec.d.ts.map +1 -1
  149. package/dist/safe-exec.js +1 -1
  150. package/dist/safe-exec.js.map +1 -1
  151. package/dist/skill-targets.d.ts.map +1 -1
  152. package/dist/skill-targets.js +3 -1
  153. package/dist/skill-targets.js.map +1 -1
  154. package/dist/skill-test/spawn-claude.d.ts +0 -15
  155. package/dist/skill-test/spawn-claude.d.ts.map +1 -1
  156. package/dist/skill-test/spawn-claude.js +11 -50
  157. package/dist/skill-test/spawn-claude.js.map +1 -1
  158. package/dist/special-file.d.ts +18 -0
  159. package/dist/special-file.d.ts.map +1 -0
  160. package/dist/special-file.js +21 -0
  161. package/dist/special-file.js.map +1 -0
  162. package/dist/terminating-signals.d.ts +129 -0
  163. package/dist/terminating-signals.d.ts.map +1 -0
  164. package/dist/terminating-signals.js +210 -0
  165. package/dist/terminating-signals.js.map +1 -0
  166. package/dist/test-helpers.d.ts +9 -5
  167. package/dist/test-helpers.d.ts.map +1 -1
  168. package/dist/test-helpers.js +18 -21
  169. package/dist/test-helpers.js.map +1 -1
  170. package/dist/test-scratch-guard.d.ts +34 -0
  171. package/dist/test-scratch-guard.d.ts.map +1 -0
  172. package/dist/test-scratch-guard.js +45 -0
  173. package/dist/test-scratch-guard.js.map +1 -0
  174. package/dist/testing/archive-fixtures.d.ts +147 -0
  175. package/dist/testing/archive-fixtures.d.ts.map +1 -0
  176. package/dist/testing/archive-fixtures.js +449 -0
  177. package/dist/testing/archive-fixtures.js.map +1 -0
  178. package/dist/testing/executables.d.ts +6 -0
  179. package/dist/testing/executables.d.ts.map +1 -1
  180. package/dist/testing/executables.js +20 -9
  181. package/dist/testing/executables.js.map +1 -1
  182. package/dist/testing/fault-fs-preload.d.ts +16 -0
  183. package/dist/testing/fault-fs-preload.d.ts.map +1 -0
  184. package/dist/testing/fault-fs-preload.js +22 -0
  185. package/dist/testing/fault-fs-preload.js.map +1 -0
  186. package/dist/testing/fault-fs.d.ts +115 -0
  187. package/dist/testing/fault-fs.d.ts.map +1 -0
  188. package/dist/testing/fault-fs.js +411 -0
  189. package/dist/testing/fault-fs.js.map +1 -0
  190. package/dist/testing/fault-spec.d.ts +83 -0
  191. package/dist/testing/fault-spec.d.ts.map +1 -0
  192. package/dist/testing/fault-spec.js +132 -0
  193. package/dist/testing/fault-spec.js.map +1 -0
  194. package/dist/testing/hostile-tree.d.ts.map +1 -1
  195. package/dist/testing/hostile-tree.js +3 -4
  196. package/dist/testing/hostile-tree.js.map +1 -1
  197. package/dist/testing/platform-gates.d.ts +8 -0
  198. package/dist/testing/platform-gates.d.ts.map +1 -1
  199. package/dist/testing/platform-gates.js +24 -0
  200. package/dist/testing/platform-gates.js.map +1 -1
  201. package/dist/testing/temp-dir.d.ts +31 -0
  202. package/dist/testing/temp-dir.d.ts.map +1 -1
  203. package/dist/testing/temp-dir.js +63 -0
  204. package/dist/testing/temp-dir.js.map +1 -1
  205. package/dist/testing/tier-timeout.d.ts +34 -0
  206. package/dist/testing/tier-timeout.d.ts.map +1 -0
  207. package/dist/testing/tier-timeout.js +45 -0
  208. package/dist/testing/tier-timeout.js.map +1 -0
  209. package/dist/testing/tree-snapshot.d.ts +71 -0
  210. package/dist/testing/tree-snapshot.d.ts.map +1 -0
  211. package/dist/testing/tree-snapshot.js +163 -0
  212. package/dist/testing/tree-snapshot.js.map +1 -0
  213. package/dist/testing.d.ts +6 -0
  214. package/dist/testing.d.ts.map +1 -1
  215. package/dist/testing.js +8 -1
  216. package/dist/testing.js.map +1 -1
  217. package/dist/text-content.d.ts +29 -0
  218. package/dist/text-content.d.ts.map +1 -1
  219. package/dist/text-content.js +64 -0
  220. package/dist/text-content.js.map +1 -1
  221. package/dist/text-file.d.ts +58 -6
  222. package/dist/text-file.d.ts.map +1 -1
  223. package/dist/text-file.js +111 -11
  224. package/dist/text-file.js.map +1 -1
  225. package/dist/text.d.ts +1 -1
  226. package/dist/text.d.ts.map +1 -1
  227. package/dist/text.js +1 -1
  228. package/dist/text.js.map +1 -1
  229. package/dist/timing-dump.d.ts.map +1 -1
  230. package/dist/timing-dump.js +2 -10
  231. package/dist/timing-dump.js.map +1 -1
  232. package/dist/tree-change/apply-decisions.d.ts +101 -0
  233. package/dist/tree-change/apply-decisions.d.ts.map +1 -0
  234. package/dist/tree-change/apply-decisions.js +139 -0
  235. package/dist/tree-change/apply-decisions.js.map +1 -0
  236. package/dist/tree-change/apply.d.ts +98 -0
  237. package/dist/tree-change/apply.d.ts.map +1 -0
  238. package/dist/tree-change/apply.js +364 -0
  239. package/dist/tree-change/apply.js.map +1 -0
  240. package/dist/tree-change/copy-decisions.d.ts +58 -0
  241. package/dist/tree-change/copy-decisions.d.ts.map +1 -0
  242. package/dist/tree-change/copy-decisions.js +66 -0
  243. package/dist/tree-change/copy-decisions.js.map +1 -0
  244. package/dist/tree-change/copy-tree.d.ts +125 -0
  245. package/dist/tree-change/copy-tree.d.ts.map +1 -0
  246. package/dist/tree-change/copy-tree.js +279 -0
  247. package/dist/tree-change/copy-tree.js.map +1 -0
  248. package/dist/tree-change/files.d.ts +167 -0
  249. package/dist/tree-change/files.d.ts.map +1 -0
  250. package/dist/tree-change/files.js +423 -0
  251. package/dist/tree-change/files.js.map +1 -0
  252. package/dist/tree-change/followed-walk.d.ts +54 -0
  253. package/dist/tree-change/followed-walk.d.ts.map +1 -0
  254. package/dist/tree-change/followed-walk.js +81 -0
  255. package/dist/tree-change/followed-walk.js.map +1 -0
  256. package/dist/tree-change/host-chain.d.ts +48 -0
  257. package/dist/tree-change/host-chain.d.ts.map +1 -0
  258. package/dist/tree-change/host-chain.js +85 -0
  259. package/dist/tree-change/host-chain.js.map +1 -0
  260. package/dist/tree-change/identity-compare.d.ts +61 -0
  261. package/dist/tree-change/identity-compare.d.ts.map +1 -0
  262. package/dist/tree-change/identity-compare.js +115 -0
  263. package/dist/tree-change/identity-compare.js.map +1 -0
  264. package/dist/tree-change/identity.d.ts +62 -0
  265. package/dist/tree-change/identity.d.ts.map +1 -0
  266. package/dist/tree-change/identity.js +152 -0
  267. package/dist/tree-change/identity.js.map +1 -0
  268. package/dist/tree-change/index.d.ts +24 -0
  269. package/dist/tree-change/index.d.ts.map +1 -0
  270. package/dist/tree-change/index.js +14 -0
  271. package/dist/tree-change/index.js.map +1 -0
  272. package/dist/tree-change/link-chain.d.ts +180 -0
  273. package/dist/tree-change/link-chain.d.ts.map +1 -0
  274. package/dist/tree-change/link-chain.js +377 -0
  275. package/dist/tree-change/link-chain.js.map +1 -0
  276. package/dist/tree-change/link-containment.d.ts +105 -0
  277. package/dist/tree-change/link-containment.d.ts.map +1 -0
  278. package/dist/tree-change/link-containment.js +196 -0
  279. package/dist/tree-change/link-containment.js.map +1 -0
  280. package/dist/tree-change/link-walk.d.ts +49 -0
  281. package/dist/tree-change/link-walk.d.ts.map +1 -0
  282. package/dist/tree-change/link-walk.js +69 -0
  283. package/dist/tree-change/link-walk.js.map +1 -0
  284. package/dist/tree-change/plan.d.ts +206 -0
  285. package/dist/tree-change/plan.d.ts.map +1 -0
  286. package/dist/tree-change/plan.js +320 -0
  287. package/dist/tree-change/plan.js.map +1 -0
  288. package/dist/tree-change/readable-tree.d.ts +44 -0
  289. package/dist/tree-change/readable-tree.d.ts.map +1 -0
  290. package/dist/tree-change/readable-tree.js +52 -0
  291. package/dist/tree-change/readable-tree.js.map +1 -0
  292. package/dist/tree-change/rollback-error.d.ts +29 -0
  293. package/dist/tree-change/rollback-error.d.ts.map +1 -0
  294. package/dist/tree-change/rollback-error.js +31 -0
  295. package/dist/tree-change/rollback-error.js.map +1 -0
  296. package/dist/tree-change/staging-names.d.ts +27 -0
  297. package/dist/tree-change/staging-names.d.ts.map +1 -0
  298. package/dist/tree-change/staging-names.js +40 -0
  299. package/dist/tree-change/staging-names.js.map +1 -0
  300. package/dist/tree-change/tree-walk.d.ts +81 -0
  301. package/dist/tree-change/tree-walk.d.ts.map +1 -0
  302. package/dist/tree-change/tree-walk.js +212 -0
  303. package/dist/tree-change/tree-walk.js.map +1 -0
  304. package/dist/win32-namespace.d.ts +24 -0
  305. package/dist/win32-namespace.d.ts.map +1 -0
  306. package/dist/win32-namespace.js +31 -0
  307. package/dist/win32-namespace.js.map +1 -0
  308. package/dist/yaml/surgical-yaml.d.ts +12 -3
  309. package/dist/yaml/surgical-yaml.d.ts.map +1 -1
  310. package/dist/yaml/surgical-yaml.js +16 -6
  311. package/dist/yaml/surgical-yaml.js.map +1 -1
  312. package/eslint/README.md +12 -4
  313. package/eslint/rules/fs-binding-scan.cjs +278 -0
  314. package/eslint/rules/no-adhoc-errno.cjs +364 -0
  315. package/eslint/rules/no-bare-symlink-in-tests.cjs +2 -3
  316. package/eslint/rules/no-blind-catch.cjs +1 -1
  317. package/eslint/rules/no-destructive-fs.cjs +359 -0
  318. package/eslint/rules/no-existssync.cjs +70 -0
  319. package/eslint/rules/no-fragile-entrypoint-guard.cjs +3 -2
  320. package/eslint/rules/no-link-following-fs.cjs +68 -0
  321. package/eslint/rules/no-literal-process-exit.cjs +96 -8
  322. package/eslint/rules/no-literal-test-timeout.cjs +214 -0
  323. package/eslint/rules/no-raw-signal-listener.cjs +224 -0
  324. package/eslint/rules/no-stdout-outside-writer.cjs +135 -0
  325. package/package.json +10 -2
  326. package/dist/errors/errno.d.ts +0 -51
  327. package/dist/errors/errno.d.ts.map +0 -1
  328. package/dist/errors/errno.js +0 -112
  329. package/dist/errors/errno.js.map +0 -1
  330. package/eslint/rules/no-fs-promises-cp.cjs +0 -43
@@ -0,0 +1,85 @@
1
+ /**
2
+ * The link-chain resolver ({@link walkLinkChain}) bound to this host's filesystem: `lstat` and
3
+ * `readlink`, and nothing that follows a link. Every call VAT makes that FOLLOWS a link — a
4
+ * `stat`, a `realpath` — reads the chain here first (`link-following.ts`, `assertLocalChain`), so
5
+ * no lane — a write lane, a read lane, an untrusted tree or the user's own — hands the kernel a
6
+ * chain whose every text has not been read.
7
+ */
8
+ import { lstatSync, readlinkSync } from 'node:fs';
9
+ import { isPathAbsentError, LINK_CHAIN_REFUSED_CODE } from '../errors/errno-table.js';
10
+ import { isVatError, VatError } from '../errors/vat-error.js';
11
+ import { safePath, toForwardSlash } from '../path-core.js';
12
+ import { MAX_LINK_HOPS, walkLinkChain } from './link-chain.js';
13
+ /**
14
+ * What stands at `path`, a link there not followed. A probe the OS refuses is thrown raw, for the
15
+ * caller to classify.
16
+ *
17
+ * ⚠️ "Not followed" is `lstat`'s word, and on Windows libuv keeps it only for what it calls a
18
+ * symbolic link: a junction to a volume (`\??\Volume{…}\`) and a reparse point of another tag
19
+ * (cloud files, dedup, WCI) are retried as a link-FOLLOWING `stat` and reported as the directory
20
+ * or file they lead to. Their targets are local — the kernel refuses a remote mount point — so no
21
+ * credential leaves the host, but the walk reads such a place as a plain directory where the
22
+ * kernel reparses it.
23
+ */
24
+ export function hostPlaceKind(path) {
25
+ try {
26
+ const stats = lstatSync(path);
27
+ if (stats.isSymbolicLink())
28
+ return 'link';
29
+ return stats.isDirectory() ? 'directory' : 'file';
30
+ }
31
+ catch (error) {
32
+ if (isPathAbsentError(error))
33
+ return 'absent';
34
+ throw error;
35
+ }
36
+ }
37
+ /** The probe of this host's filesystem: `lstat` and `readlink` alone. */
38
+ const HOST_PROBE = { kindAt: hostPlaceKind, textAt: (path) => readlinkSync(path) };
39
+ /**
40
+ * Where `path` leads on this host's filesystem, under `rule` ({@link walkLinkChain}).
41
+ *
42
+ * @param path - Absolute, or relative to cwd; either separator
43
+ * @param rule - The flavor (bound from the host at the edge), the tree, and what the chain may do outside it
44
+ * @throws The raw errno of an `lstat` or `readlink` the OS refused, for the caller to classify
45
+ */
46
+ export function walkHostChain(path, rule) {
47
+ return walkLinkChain(toForwardSlash(safePath.resolve(path)), rule, HOST_PROBE);
48
+ }
49
+ /** How each refusal reads, after "the symbolic link <link> ". */
50
+ function refusalClause(refusal) {
51
+ switch (refusal.why) {
52
+ case 'network':
53
+ return `leads to ${refusal.text}, a network or device path, which VAT never asks the OS to follow (a Windows host would offer the operator's credentials to it)`;
54
+ case 'hop-limit':
55
+ return `starts a chain of more than ${MAX_LINK_HOPS.toString()} symbolic links that is not a cycle, so where it ends was never read`;
56
+ case 'unportable':
57
+ return `has a text no kernel resolves as written (${JSON.stringify(refusal.text)}: a NUL, or a name ending in a dot or a space)`;
58
+ case 'absolute':
59
+ case 'drive-relative':
60
+ case 'climbs-out':
61
+ return `leads outside the tree it is in (${refusal.text})`;
62
+ }
63
+ }
64
+ /**
65
+ * A path VAT would not resolve: a link on the way to it leads to a network path, or the chain is
66
+ * longer than any kernel follows. A read lane records it as that one target's fault
67
+ * (`linkResolutionFault`); a lane that stops classifies it on its own side, like any refusal
68
+ * (`classifyFsFault`), so a destination's refused chain reads as the destination's.
69
+ */
70
+ export class LinkChainRefusedError extends VatError {
71
+ /** The path whose resolution was asked. */
72
+ path;
73
+ /** Why, with the link whose text decided it. */
74
+ refusal;
75
+ constructor(path, refusal) {
76
+ super(LINK_CHAIN_REFUSED_CODE, `Refusing to resolve ${path}: the symbolic link ${refusal.link} ${refusalClause(refusal)} — replace the link with the files it names.`);
77
+ this.path = path;
78
+ this.refusal = refusal;
79
+ }
80
+ }
81
+ /** Whether `error` is a {@link LinkChainRefusedError}, by its code (a `dist` copy never `instanceof`-matches a `src` one). */
82
+ export function isLinkChainRefusedError(error) {
83
+ return isVatError(error, LINK_CHAIN_REFUSED_CODE) && 'refusal' in error;
84
+ }
85
+ //# sourceMappingURL=host-chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-chain.js","sourceRoot":"","sources":["../../src/tree-change/host-chain.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAsE,aAAa,EAAkB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEnJ;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,KAAK,CAAC,cAAc,EAAE;YAAE,OAAO,MAAM,CAAC;QAC1C,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;IACpD,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,iBAAiB,CAAC,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC;QAC9C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,GAAe,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;AAE/F;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,IAAe;IACzD,OAAO,aAAa,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AACjF,CAAC;AAED,iEAAiE;AACjE,SAAS,aAAa,CAAC,OAAqB;IAC1C,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,YAAY,OAAO,CAAC,IAAI,iIAAiI,CAAC;QACnK,KAAK,WAAW;YACd,OAAO,+BAA+B,aAAa,CAAC,QAAQ,EAAE,sEAAsE,CAAC;QACvI,KAAK,YAAY;YACf,OAAO,6CAA6C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,gDAAgD,CAAC;QACnI,KAAK,UAAU,CAAC;QAChB,KAAK,gBAAgB,CAAC;QACtB,KAAK,YAAY;YACf,OAAO,oCAAoC,OAAO,CAAC,IAAI,GAAG,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,qBAAsB,SAAQ,QAAQ;IACjD,2CAA2C;IAClC,IAAI,CAAS;IACtB,gDAAgD;IACvC,OAAO,CAAe;IAC/B,YAAY,IAAY,EAAE,OAAqB;QAC7C,KAAK,CAAC,uBAAuB,EAAE,uBAAuB,IAAI,uBAAuB,OAAO,CAAC,IAAI,IAAI,aAAa,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC;QACvK,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,8HAA8H;AAC9H,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACpD,OAAO,UAAU,CAAC,KAAK,EAAE,uBAAuB,CAAC,IAAI,SAAS,IAAI,KAAK,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Deciding sameness and containment from entry identities already read off the filesystem.
3
+ * Pure: the examination is handed in, so the decision is the same whoever asked the OS.
4
+ */
5
+ /** One way an entry answers to being identified: a filesystem id, or a folded real path when the filesystem reports none. */
6
+ export type Identity = {
7
+ readonly id: string;
8
+ } | {
9
+ readonly foldedRealPath: string;
10
+ };
11
+ /** Whether two entries are one. `unknown` means it could not be decided: treat it as `same` when deciding whether to delete. */
12
+ export type EntrySameness = 'same' | 'different' | 'unknown';
13
+ /** Whether an entry lies strictly under another. `unknown` means it could not be decided. */
14
+ export type EntryContainment = 'inside' | 'outside' | 'unknown';
15
+ /** What one round of identity questions needs: each entry's identities, or `undefined` when the OS refuses to examine it. */
16
+ export type Examiner = (entry: string) => readonly Identity[] | undefined;
17
+ export declare function sameBy(examine: Examiner, a: string, b: string): EntrySameness;
18
+ /**
19
+ * Where an entry physically is: every spelling of it with no link left in its directories (its own
20
+ * place, and — for a link — its target's), or `undefined` when the OS refuses to resolve it.
21
+ */
22
+ export type PhysicalSpellings = (entry: string) => readonly string[] | undefined;
23
+ /**
24
+ * Whether `child` lies strictly under `ancestor`: some directory above it IS the ancestor. Walked
25
+ * along the spelling given AND along every physical spelling of the child — a directory of the given
26
+ * spelling that is a link to somewhere BELOW the ancestor is neither the ancestor nor a link to it,
27
+ * and the directories between its target and the ancestor are only on the physical way up.
28
+ */
29
+ export declare function insideBy(examine: Examiner, child: string, ancestor: string, physical: PhysicalSpellings): EntryContainment;
30
+ /**
31
+ * The identity a `stat` answers with: the filesystem's own id when it reports both a device and an
32
+ * inode, else the fold — which is only computed then, since it costs a `realpath`.
33
+ *
34
+ * @param stats - The `dev` and `ino` of a `bigint` stat
35
+ * @param fold - The folded real path, for a filesystem that reports no inode
36
+ */
37
+ export declare function identityOf(stats: {
38
+ readonly dev: bigint;
39
+ readonly ino: bigint;
40
+ }, fold: () => Identity): Identity;
41
+ /** Sameness and containment over one memo, and the one throwing examination of an entry they share. */
42
+ export interface IdentityOracle {
43
+ /** The entry's identities, read once: a refusal is remembered and thrown again. */
44
+ readonly identities: (entry: string) => readonly Identity[];
45
+ /** Whether the OS refuses to examine `entry` (the remembered answer of {@link IdentityOracle.identities}). */
46
+ readonly refuses: (entry: string) => boolean;
47
+ readonly sameEntry: (a: string, b: string) => EntrySameness;
48
+ readonly isInside: (child: string, ancestor: string) => EntryContainment;
49
+ }
50
+ /**
51
+ * Identity questions that examine each entry ONCE: every answer is built from the same
52
+ * observation of each entry. One plan's decisions asked the filesystem again and again,
53
+ * so a refusal seen by one (subsumption: `unknown`) and not by the next (the overlap
54
+ * check: `inside`) made the planner refuse its own plan.
55
+ *
56
+ * @param read - The examination: an entry's identities, or a thrown classified fault when the OS
57
+ * refuses. Anything else it throws is a defect and is never remembered as a refusal.
58
+ * @param physical - Where an entry physically is, for containment (see {@link insideBy})
59
+ */
60
+ export declare function identityOracleOver(read: (entry: string) => readonly Identity[], physical: PhysicalSpellings): IdentityOracle;
61
+ //# sourceMappingURL=identity-compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-compare.d.ts","sourceRoot":"","sources":["../../src/tree-change/identity-compare.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,6HAA6H;AAC7H,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAErF,gIAAgI;AAChI,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;AAE7D,6FAA6F;AAC7F,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAkBhE,6HAA6H;AAC7H,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,QAAQ,EAAE,GAAG,SAAS,CAAC;AAE1E,wBAAgB,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,aAAa,CAI7E;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;AAgBjF;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,gBAAgB,CAO1H;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,EAAE,MAAM,QAAQ,GAAG,QAAQ,CAEhH;AAED,uGAAuG;AACvG,MAAM,WAAW,cAAc;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,QAAQ,EAAE,CAAC;IAC5D,8GAA8G;IAC9G,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,aAAa,CAAC;IAC5D,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,gBAAgB,CAAC;CAC1E;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,QAAQ,EAAE,EAAE,QAAQ,EAAE,iBAAiB,GAAG,cAAc,CA8B5H"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Deciding sameness and containment from entry identities already read off the filesystem.
3
+ * Pure: the examination is handed in, so the decision is the same whoever asked the OS.
4
+ */
5
+ import path from 'node:path';
6
+ import { isFsFaultError } from '../errors/fs-fault.js';
7
+ function hasFold(identities) {
8
+ return identities.some((identity) => 'foldedRealPath' in identity);
9
+ }
10
+ /** One entry when both are filesystem ids and equal, or both are folds and equal; an id never equals a fold. */
11
+ function sameIdentity(left, right) {
12
+ if ('id' in left && 'id' in right)
13
+ return left.id === right.id;
14
+ return 'foldedRealPath' in left && 'foldedRealPath' in right && left.foldedRealPath === right.foldedRealPath;
15
+ }
16
+ function compare(left, right) {
17
+ if (left.length === 0 || right.length === 0)
18
+ return 'different';
19
+ if (left.some((l) => right.some((r) => sameIdentity(l, r))))
20
+ return 'same';
21
+ return hasFold(left) || hasFold(right) ? 'unknown' : 'different';
22
+ }
23
+ export function sameBy(examine, a, b) {
24
+ const left = examine(a);
25
+ const right = examine(b);
26
+ return left === undefined || right === undefined ? 'unknown' : compare(left, right);
27
+ }
28
+ /** Whether some directory above `start`, spelled as given, is the wanted entry. */
29
+ function ancestorAbove(examine, start, wanted) {
30
+ let undecided = false;
31
+ let current = start;
32
+ for (let parent = path.dirname(current); parent !== current; parent = path.dirname(current)) {
33
+ const found = examine(parent);
34
+ const verdict = found === undefined ? 'unknown' : compare(found, wanted);
35
+ if (verdict === 'same')
36
+ return 'inside';
37
+ if (verdict === 'unknown')
38
+ undecided = true;
39
+ current = parent;
40
+ }
41
+ return undecided ? 'unknown' : 'outside';
42
+ }
43
+ /**
44
+ * Whether `child` lies strictly under `ancestor`: some directory above it IS the ancestor. Walked
45
+ * along the spelling given AND along every physical spelling of the child — a directory of the given
46
+ * spelling that is a link to somewhere BELOW the ancestor is neither the ancestor nor a link to it,
47
+ * and the directories between its target and the ancestor are only on the physical way up.
48
+ */
49
+ export function insideBy(examine, child, ancestor, physical) {
50
+ const wanted = examine(ancestor);
51
+ if (wanted === undefined)
52
+ return 'unknown';
53
+ const resolved = physical(child);
54
+ const verdicts = new Set([...new Set([child, ...(resolved ?? [])])].map((start) => ancestorAbove(examine, start, wanted)));
55
+ if (verdicts.has('inside'))
56
+ return 'inside';
57
+ return resolved === undefined || verdicts.has('unknown') ? 'unknown' : 'outside';
58
+ }
59
+ /**
60
+ * The identity a `stat` answers with: the filesystem's own id when it reports both a device and an
61
+ * inode, else the fold — which is only computed then, since it costs a `realpath`.
62
+ *
63
+ * @param stats - The `dev` and `ino` of a `bigint` stat
64
+ * @param fold - The folded real path, for a filesystem that reports no inode
65
+ */
66
+ export function identityOf(stats, fold) {
67
+ return stats.dev !== 0n && stats.ino !== 0n ? { id: `${stats.dev}:${stats.ino}` } : fold();
68
+ }
69
+ /**
70
+ * Identity questions that examine each entry ONCE: every answer is built from the same
71
+ * observation of each entry. One plan's decisions asked the filesystem again and again,
72
+ * so a refusal seen by one (subsumption: `unknown`) and not by the next (the overlap
73
+ * check: `inside`) made the planner refuse its own plan.
74
+ *
75
+ * @param read - The examination: an entry's identities, or a thrown classified fault when the OS
76
+ * refuses. Anything else it throws is a defect and is never remembered as a refusal.
77
+ * @param physical - Where an entry physically is, for containment (see {@link insideBy})
78
+ */
79
+ export function identityOracleOver(read, physical) {
80
+ const memo = new Map();
81
+ const identities = (entry) => {
82
+ let seen = memo.get(entry);
83
+ if (seen === undefined) {
84
+ try {
85
+ seen = { ok: read(entry) };
86
+ }
87
+ catch (error) {
88
+ if (!isFsFaultError(error))
89
+ throw error;
90
+ seen = { refused: error };
91
+ }
92
+ memo.set(entry, seen);
93
+ }
94
+ if ('refused' in seen)
95
+ throw seen.refused;
96
+ return seen.ok;
97
+ };
98
+ const undecided = (entry) => {
99
+ try {
100
+ return identities(entry);
101
+ }
102
+ catch (error) {
103
+ if (isFsFaultError(error))
104
+ return undefined;
105
+ throw error;
106
+ }
107
+ };
108
+ return {
109
+ identities,
110
+ refuses: (entry) => undecided(entry) === undefined,
111
+ sameEntry: (a, b) => sameBy(undecided, a, b),
112
+ isInside: (child, ancestor) => insideBy(undecided, child, ancestor, physical),
113
+ };
114
+ }
115
+ //# sourceMappingURL=identity-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-compare.js","sourceRoot":"","sources":["../../src/tree-change/identity-compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Entry identity: are two names ONE entry on disk?
3
+ *
4
+ * Two changes to a tree can alias without sharing a spelling — `plugins/Old` and
5
+ * `plugins/old` on APFS or NTFS, a link and its target, two links to one target.
6
+ * Comparing names cannot see it, and acting on a wrong "different" deletes what the
7
+ * user just installed. So identity is asked of the filesystem:
8
+ *
9
+ * - `dev` and `ino` both nonzero → the id `${dev}:${ino}`, from a `bigint` `lstat` of
10
+ * the entry, plus a `stat` of a link's target. A link answers to BOTH: removing it
11
+ * removes only the link, but it aliases its target.
12
+ * - Otherwise (a filesystem that reports `ino` 0) → a folded real path: the real
13
+ * parent, a `/`, the base name, NFC then lower-cased. The fold can only err toward
14
+ * "same", which keeps what it is asked to remove.
15
+ *
16
+ * An entry the OS refuses to examine is `unknown`, never `different`: the caller
17
+ * keeps. {@link entryIdentities} throws the refusal as an `FsFaultError` on the side
18
+ * the CALLER names, so whatever surfaces it reports a classified fault, not a raw errno.
19
+ */
20
+ import { type FsSide } from '../errors/fs-fault.js';
21
+ import { type EntryContainment, type EntrySameness, type Identity, type IdentityOracle } from './identity-compare.js';
22
+ /**
23
+ * Every identity `entry` answers to: `[]` when nothing is there; its own (`lstat`) for
24
+ * anything; plus its target's (`stat`) when it is a link that resolves.
25
+ *
26
+ * @param entry - Absolute path to identify
27
+ * @param side - The side of the verb that named `entry`; every fault (the `lstat`, the `stat`, the real path of a fold) is raised on it
28
+ * @throws FsFaultError on `side` when the OS refuses to examine `entry`
29
+ */
30
+ export declare function entryIdentities(entry: string, side: FsSide): readonly Identity[];
31
+ /**
32
+ * Whether `a` and `b` are one entry. Any shared identity is `same`; identities on
33
+ * both sides with a filesystem id each and none shared is `different`; a folded path
34
+ * on either side that does not match is `unknown`; an entry the OS refuses to
35
+ * examine is `unknown`; an absent entry is `different` (nothing there can alias).
36
+ *
37
+ * @param a - Absolute path
38
+ * @param b - Absolute path
39
+ */
40
+ export declare function sameEntry(a: string, b: string): EntrySameness;
41
+ /**
42
+ * Whether `child` lies strictly under `ancestor`, judged by identity: some directory
43
+ * on the way up from `child` — along its spelling as given, and along where it
44
+ * physically is — is the same entry as `ancestor`. So a linked or case-aliased
45
+ * spelling of the ancestor is found, and so is a directory of `child`'s spelling that
46
+ * is a link to somewhere BELOW the ancestor. `child` need not exist.
47
+ * `unknown` when no ancestor proved `same` and one could not be examined.
48
+ *
49
+ * ⚠️ On a filesystem that reports `ino` 0 the answer for an existing `ancestor` is
50
+ * `unknown`, never `outside`: a fold cannot prove two names apart. A caller that
51
+ * refuses on `inside` must not refuse on `unknown`, or every copy there is refused.
52
+ *
53
+ * @param child - Absolute path
54
+ * @param ancestor - Absolute path
55
+ */
56
+ export declare function isInsideByIdentity(child: string, ancestor: string): EntryContainment;
57
+ /**
58
+ * {@link sameEntry} and {@link isInsideByIdentity} over one memo: each entry is examined once
59
+ * (`entryIdentities(entry, 'destination')`), so every answer of a plan is built from one observation.
60
+ */
61
+ export declare function identityOracle(): IdentityOracle;
62
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/tree-change/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,OAAO,EAA+C,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAMjG,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAc,KAAK,cAAc,EAAwC,MAAM,uBAAuB,CAAC;AAkCxK;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,QAAQ,EAAE,CAYhF;AA8BD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,aAAa,CAE7D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAEpF;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,cAAc,CAE/C"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Entry identity: are two names ONE entry on disk?
3
+ *
4
+ * Two changes to a tree can alias without sharing a spelling — `plugins/Old` and
5
+ * `plugins/old` on APFS or NTFS, a link and its target, two links to one target.
6
+ * Comparing names cannot see it, and acting on a wrong "different" deletes what the
7
+ * user just installed. So identity is asked of the filesystem:
8
+ *
9
+ * - `dev` and `ino` both nonzero → the id `${dev}:${ino}`, from a `bigint` `lstat` of
10
+ * the entry, plus a `stat` of a link's target. A link answers to BOTH: removing it
11
+ * removes only the link, but it aliases its target.
12
+ * - Otherwise (a filesystem that reports `ino` 0) → a folded real path: the real
13
+ * parent, a `/`, the base name, NFC then lower-cased. The fold can only err toward
14
+ * "same", which keeps what it is asked to remove.
15
+ *
16
+ * An entry the OS refuses to examine is `unknown`, never `different`: the caller
17
+ * keeps. {@link entryIdentities} throws the refusal as an `FsFaultError` on the side
18
+ * the CALLER names, so whatever surfaces it reports a classified fault, not a raw errno.
19
+ */
20
+ import { lstatSync } from 'node:fs';
21
+ import path from 'node:path';
22
+ import { requireConfirmedAbsent } from '../errors/confirmed-absent.js';
23
+ import { isPathAbsentError } from '../errors/errno-table.js';
24
+ import { classifyFsFault, everywhere, isFsFaultError } from '../errors/fs-fault.js';
25
+ import { edgeBigintStatSync } from '../link-following.js';
26
+ import { canonicalPath } from '../path-containment.js';
27
+ import { safePath, toForwardSlash, toNfc } from '../path-core.js';
28
+ import { normalizePath } from '../path-utils.js';
29
+ import { identityOf, identityOracleOver, insideBy, sameBy } from './identity-compare.js';
30
+ /** Run `work` for `entry`; a filesystem refusal is rethrown classified on `side`, anything else as it was. */
31
+ function guarded(entry, side, work) {
32
+ try {
33
+ return work();
34
+ }
35
+ catch (error) {
36
+ throw classifyFsFault(error, { side, action: 'examine the entry', path: entry });
37
+ }
38
+ }
39
+ /** The fold of `real` (an absolute path): its real parent, a `/`, its base name, NFC then lower-cased. */
40
+ function foldedRealPath(entry, side, real) {
41
+ return guarded(entry, side, () => ({
42
+ foldedRealPath: toNfc(`${toForwardSlash(normalizePath(path.dirname(real), path.dirname(real)))}/${path.basename(real)}`).toLowerCase(),
43
+ }));
44
+ }
45
+ /**
46
+ * `stat(entry)` for an entry that may be absent: `undefined` when nothing is there — believed only when
47
+ * the parent's listing agrees — and a classified fault when the OS refuses.
48
+ */
49
+ function examine(entry, side, follows) {
50
+ const ctx = { side, action: 'examine the entry', path: entry };
51
+ try {
52
+ return follows ? edgeBigintStatSync(entry) : lstatSync(entry, { bigint: true });
53
+ }
54
+ catch (error) {
55
+ if (!isPathAbsentError(error))
56
+ throw classifyFsFault(error, ctx);
57
+ // A `stat` follows a link (a dangling one is absent); an `lstat` sees the link itself.
58
+ requireConfirmedAbsent(entry, error, { action: ctx.action, path: entry }, { follows, sideOf: everywhere(side) });
59
+ return undefined;
60
+ }
61
+ }
62
+ /**
63
+ * Every identity `entry` answers to: `[]` when nothing is there; its own (`lstat`) for
64
+ * anything; plus its target's (`stat`) when it is a link that resolves.
65
+ *
66
+ * @param entry - Absolute path to identify
67
+ * @param side - The side of the verb that named `entry`; every fault (the `lstat`, the `stat`, the real path of a fold) is raised on it
68
+ * @throws FsFaultError on `side` when the OS refuses to examine `entry`
69
+ */
70
+ export function entryIdentities(entry, side) {
71
+ const own = examine(entry, side, false);
72
+ if (own === undefined)
73
+ return [];
74
+ const identities = [identityOf(own, () => foldedRealPath(entry, side, entry))];
75
+ if (!own.isSymbolicLink())
76
+ return identities;
77
+ // Every entry identified here is one the verb itself names (a destination it writes or removes):
78
+ // the operator's own path, its own link the edge the kernel answers.
79
+ const target = examine(entry, side, true);
80
+ if (target !== undefined) {
81
+ identities.push(identityOf(target, () => foldedRealPath(entry, side, guarded(entry, side, () => normalizePath(entry, entry)))));
82
+ }
83
+ return identities;
84
+ }
85
+ /**
86
+ * The identities of `entry`, or `undefined` when the OS refuses to examine it. The
87
+ * side is irrelevant here: a refusal becomes `unknown` and never surfaces.
88
+ */
89
+ function identitiesOrUndecided(entry) {
90
+ try {
91
+ return entryIdentities(entry, 'destination');
92
+ }
93
+ catch (error) {
94
+ if (isFsFaultError(error))
95
+ return undefined;
96
+ throw error;
97
+ }
98
+ }
99
+ /**
100
+ * Where `entry` physically is — its own place (its real parent directory, then its name) and, for a
101
+ * link, its target's — or `undefined` when the OS refuses to resolve it. `entry` need not exist: it
102
+ * is resolved from its deepest existing ancestor.
103
+ */
104
+ function physicalSpellings(entry) {
105
+ try {
106
+ return [safePath.join(canonicalPath(path.dirname(entry), path.dirname(entry)), path.basename(entry)), canonicalPath(entry, entry)];
107
+ }
108
+ catch (error) {
109
+ // A refusal is `unknown` to the caller, exactly as an entry it cannot examine is; a defect stays loud.
110
+ if (isFsFaultError(classifyFsFault(error, { side: 'destination', action: 'resolve the entry', path: entry })))
111
+ return undefined;
112
+ throw error;
113
+ }
114
+ }
115
+ /**
116
+ * Whether `a` and `b` are one entry. Any shared identity is `same`; identities on
117
+ * both sides with a filesystem id each and none shared is `different`; a folded path
118
+ * on either side that does not match is `unknown`; an entry the OS refuses to
119
+ * examine is `unknown`; an absent entry is `different` (nothing there can alias).
120
+ *
121
+ * @param a - Absolute path
122
+ * @param b - Absolute path
123
+ */
124
+ export function sameEntry(a, b) {
125
+ return sameBy(identitiesOrUndecided, a, b);
126
+ }
127
+ /**
128
+ * Whether `child` lies strictly under `ancestor`, judged by identity: some directory
129
+ * on the way up from `child` — along its spelling as given, and along where it
130
+ * physically is — is the same entry as `ancestor`. So a linked or case-aliased
131
+ * spelling of the ancestor is found, and so is a directory of `child`'s spelling that
132
+ * is a link to somewhere BELOW the ancestor. `child` need not exist.
133
+ * `unknown` when no ancestor proved `same` and one could not be examined.
134
+ *
135
+ * ⚠️ On a filesystem that reports `ino` 0 the answer for an existing `ancestor` is
136
+ * `unknown`, never `outside`: a fold cannot prove two names apart. A caller that
137
+ * refuses on `inside` must not refuse on `unknown`, or every copy there is refused.
138
+ *
139
+ * @param child - Absolute path
140
+ * @param ancestor - Absolute path
141
+ */
142
+ export function isInsideByIdentity(child, ancestor) {
143
+ return insideBy(identitiesOrUndecided, child, ancestor, physicalSpellings);
144
+ }
145
+ /**
146
+ * {@link sameEntry} and {@link isInsideByIdentity} over one memo: each entry is examined once
147
+ * (`entryIdentities(entry, 'destination')`), so every answer of a plan is built from one observation.
148
+ */
149
+ export function identityOracle() {
150
+ return identityOracleOver((entry) => entryIdentities(entry, 'destination'), physicalSpellings);
151
+ }
152
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/tree-change/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /** The plan/apply tree-change primitive: entry identity, the readable-tree proof and the copy, the planner, the applier and the file helpers. */
2
+ export { entryIdentities, isInsideByIdentity, sameEntry } from './identity.js';
3
+ export type { EntryContainment, EntrySameness, Identity } from './identity-compare.js';
4
+ export { COPY_LINK_ESCAPES_SOURCE_CODE, CopyLinkEscapesSourceError, DIRECTORY_WALK_REVISITED_CODE, DirectoryWalkRevisitedError, FollowedWalk, } from './followed-walk.js';
5
+ export { proveTreeReadable, readRegularFile } from './readable-tree.js';
6
+ export type { ProveTreeReadableOptions } from './readable-tree.js';
7
+ export { copyRegularFile, copyTree } from './copy-tree.js';
8
+ export type { CopyRegularFileOptions, CopyTreeOptions } from './copy-tree.js';
9
+ export type { CopyOnto } from './copy-decisions.js';
10
+ export type { LinkPolicy, TreeWalkOptions } from './tree-walk.js';
11
+ export { refuseEscapingLinks, treeChain, treeContainment } from './link-containment.js';
12
+ export type { LinkContainmentCheck } from './link-containment.js';
13
+ export { isLinkChainRefusedError } from './host-chain.js';
14
+ export { HOST_PATH_FLAVOR, isWithinUnder, untrustedLinkRefusal, untrustedTextRefusal, win32FoldedName } from './link-chain.js';
15
+ export { planTreeChanges, TREE_DEST_HOLDS_SOURCE_CODE, TREE_DEST_NOT_OWNED_CODE, TREE_DEST_OCCUPIED_CODE, TREE_DESTS_OVERLAP_CODE, TREE_SOURCE_HOLDS_DEST_CODE, } from './plan.js';
16
+ export type { EntryKind, FileContents, Ownership, OwnershipVerdict, PlannedAction, PlannedChange, TreeChange, TreeFill, TreePlan } from './plan.js';
17
+ export { applyTreePlan, applyTreePlanOrLeftover, TREE_CLEANUP_INCOMPLETE_CODE } from './apply.js';
18
+ export { TREE_ROLLBACK_INCOMPLETE_CODE, TreeRollbackIncompleteError } from './rollback-error.js';
19
+ export type { TreeRollbackStranded } from './rollback-error.js';
20
+ export type { ApplyOptions, ApplyOutcome, ApplyResult, TreeChangeWarning } from './apply.js';
21
+ export type { TempDirOutcome } from './files.js';
22
+ export { disposeTempDir, disposeTempDirAfterFailure, disposeTempDirSync, makeDirectoryUnder, renameFileAtomic, replaceFile, TEMP_DIR_OUTSIDE_TMPDIR_CODE, withTempDir, writeFileUnder } from './files.js';
23
+ export { isParkedTreeEntry, isTreeChangeResidue } from './staging-names.js';
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tree-change/index.ts"],"names":[],"mappings":"AAAA,iJAAiJ;AACjJ,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/E,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,6BAA6B,EAC7B,2BAA2B,EAC3B,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACxE,YAAY,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9E,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxF,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/H,OAAO,EACL,eAAe,EACf,2BAA2B,EAC3B,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpJ,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,EAAE,6BAA6B,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AACjG,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC7F,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,4BAA4B,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC1M,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /** The plan/apply tree-change primitive: entry identity, the readable-tree proof and the copy, the planner, the applier and the file helpers. */
2
+ export { entryIdentities, isInsideByIdentity, sameEntry } from './identity.js';
3
+ export { COPY_LINK_ESCAPES_SOURCE_CODE, CopyLinkEscapesSourceError, DIRECTORY_WALK_REVISITED_CODE, DirectoryWalkRevisitedError, FollowedWalk, } from './followed-walk.js';
4
+ export { proveTreeReadable, readRegularFile } from './readable-tree.js';
5
+ export { copyRegularFile, copyTree } from './copy-tree.js';
6
+ export { refuseEscapingLinks, treeChain, treeContainment } from './link-containment.js';
7
+ export { isLinkChainRefusedError } from './host-chain.js';
8
+ export { HOST_PATH_FLAVOR, isWithinUnder, untrustedLinkRefusal, untrustedTextRefusal, win32FoldedName } from './link-chain.js';
9
+ export { planTreeChanges, TREE_DEST_HOLDS_SOURCE_CODE, TREE_DEST_NOT_OWNED_CODE, TREE_DEST_OCCUPIED_CODE, TREE_DESTS_OVERLAP_CODE, TREE_SOURCE_HOLDS_DEST_CODE, } from './plan.js';
10
+ export { applyTreePlan, applyTreePlanOrLeftover, TREE_CLEANUP_INCOMPLETE_CODE } from './apply.js';
11
+ export { TREE_ROLLBACK_INCOMPLETE_CODE, TreeRollbackIncompleteError } from './rollback-error.js';
12
+ export { disposeTempDir, disposeTempDirAfterFailure, disposeTempDirSync, makeDirectoryUnder, renameFileAtomic, replaceFile, TEMP_DIR_OUTSIDE_TMPDIR_CODE, withTempDir, writeFileUnder } from './files.js';
13
+ export { isParkedTreeEntry, isTreeChangeResidue } from './staging-names.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tree-change/index.ts"],"names":[],"mappings":"AAAA,iJAAiJ;AACjJ,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,6BAA6B,EAC7B,2BAA2B,EAC3B,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI3D,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExF,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/H,OAAO,EACL,eAAe,EACf,2BAA2B,EAC3B,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,EAAE,6BAA6B,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAIjG,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,4BAA4B,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC1M,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}