@openclaw/fs-safe 0.15.0 → 0.17.0
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/CHANGELOG.md +86 -0
- package/README.md +36 -7
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +2 -8
- package/dist/advanced.d.ts +3 -0
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +3 -0
- package/dist/archive-deadline.d.ts.map +1 -1
- package/dist/archive-deadline.js +22 -23
- package/dist/archive-kind.d.ts +0 -1
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +5 -17
- package/dist/archive-merge.d.ts +1 -0
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +4 -4
- package/dist/archive-native.d.ts +1 -0
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +1 -0
- package/dist/archive-options.d.ts +2 -0
- package/dist/archive-options.d.ts.map +1 -1
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +6 -7
- package/dist/archive-tar-stream.d.ts +3 -0
- package/dist/archive-tar-stream.d.ts.map +1 -1
- package/dist/archive-tar-stream.js +56 -37
- package/dist/archive-tar-wasm.d.ts +16 -4
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +134 -34
- package/dist/archive-zip-count.d.ts.map +1 -1
- package/dist/archive-zip-count.js +21 -1
- package/dist/archive-zip-directory.d.ts.map +1 -1
- package/dist/archive-zip-directory.js +23 -1
- package/dist/archive-zip-loader.d.ts +2 -0
- package/dist/archive-zip-loader.d.ts.map +1 -1
- package/dist/archive-zip-loader.js +7 -0
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +7 -2
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +14 -9
- package/dist/byte-view.d.ts +3 -0
- package/dist/byte-view.d.ts.map +1 -0
- package/dist/byte-view.js +13 -0
- package/dist/clone-metadata.d.ts +1 -0
- package/dist/clone-metadata.d.ts.map +1 -1
- package/dist/clone-metadata.js +6 -2
- package/dist/create-directory.d.ts +20 -0
- package/dist/create-directory.d.ts.map +1 -0
- package/dist/create-directory.js +130 -0
- package/dist/create-file-async.d.ts +7 -0
- package/dist/create-file-async.d.ts.map +1 -0
- package/dist/create-file-async.js +121 -0
- package/dist/create-file.d.ts +8 -0
- package/dist/create-file.d.ts.map +1 -0
- package/dist/create-file.js +190 -0
- package/dist/create-owned-file.d.ts +8 -0
- package/dist/create-owned-file.d.ts.map +1 -0
- package/dist/create-owned-file.js +16 -0
- package/dist/create.d.ts +4 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +2 -0
- package/dist/creation-darwin.d.ts +6 -0
- package/dist/creation-darwin.d.ts.map +1 -0
- package/dist/creation-darwin.js +70 -0
- package/dist/creation-file-state.d.ts +19 -0
- package/dist/creation-file-state.d.ts.map +1 -0
- package/dist/creation-file-state.js +118 -0
- package/dist/creation-path.d.ts +21 -0
- package/dist/creation-path.d.ts.map +1 -0
- package/dist/creation-path.js +71 -0
- package/dist/creation-permissions.d.ts +19 -0
- package/dist/creation-permissions.d.ts.map +1 -0
- package/dist/creation-permissions.js +125 -0
- package/dist/directory-durability.d.ts +7 -7
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +22 -80
- package/dist/directory-guard.d.ts +3 -0
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-mode-node.d.ts +2 -0
- package/dist/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +8 -0
- package/dist/directory-receipt.d.ts +24 -0
- package/dist/directory-receipt.d.ts.map +1 -0
- package/dist/directory-receipt.js +123 -0
- package/dist/file-cleanup.d.ts +20 -0
- package/dist/file-cleanup.d.ts.map +1 -0
- package/dist/file-cleanup.js +81 -0
- package/dist/file-contents.d.ts +6 -0
- package/dist/file-contents.d.ts.map +1 -0
- package/dist/file-contents.js +40 -0
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +16 -4
- package/dist/file-lock-sync-root-acquire.d.ts.map +1 -1
- package/dist/file-lock-sync-root-acquire.js +3 -0
- package/dist/file-lock-sync-root-held.d.ts +1 -2
- package/dist/file-lock-sync-root-held.d.ts.map +1 -1
- package/dist/file-lock-sync-root-held.js +7 -5
- package/dist/file-lock-sync-stale-admission.d.ts.map +1 -1
- package/dist/file-lock-sync-stale-admission.js +3 -0
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +8 -11
- package/dist/file-observation.d.ts +1 -1
- package/dist/file-observation.d.ts.map +1 -1
- package/dist/file-store-boundary.d.ts +2 -6
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +3 -9
- package/dist/file-store-sync-write.d.ts.map +1 -1
- package/dist/file-store-sync-write.js +2 -5
- package/dist/file-store.js +3 -3
- package/dist/guarded-mkdir.d.ts +1 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +27 -19
- package/dist/install-path.d.ts.map +1 -1
- package/dist/install-path.js +2 -5
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +2 -6
- package/dist/json-durable-queue-paths.d.ts.map +1 -1
- package/dist/json-durable-queue-paths.js +2 -24
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +10 -9
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +32 -75
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +19 -21
- package/dist/move-path-cleanup.d.ts +5 -19
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +57 -21
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +63 -40
- package/dist/native-binding.d.ts +11 -1
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-fallback-warning.d.ts +4 -0
- package/dist/native-fallback-warning.d.ts.map +1 -0
- package/dist/native-fallback-warning.js +11 -0
- package/dist/native-operations.d.ts +0 -2
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -24
- package/dist/native-parent-admission.d.ts +2 -0
- package/dist/native-parent-admission.d.ts.map +1 -1
- package/dist/native-parent-admission.js +3 -2
- package/dist/native-pinned-write-windows.d.ts +1 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +173 -28
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +19 -3
- package/dist/native-policy-parent-windows.d.ts.map +1 -1
- package/dist/native-policy-parent-windows.js +15 -6
- package/dist/native-staged-file.d.ts +5 -3
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +90 -40
- package/dist/native.js +2 -2
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +11 -2
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +10 -4
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +2 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +3 -17
- package/dist/pinned-write-input.d.ts +4 -0
- package/dist/pinned-write-input.d.ts.map +1 -0
- package/dist/pinned-write-input.js +35 -0
- package/dist/pinned-write-mode.d.ts +5 -0
- package/dist/pinned-write-mode.d.ts.map +1 -0
- package/dist/pinned-write-mode.js +31 -0
- package/dist/pinned-write-staged.d.ts +6 -0
- package/dist/pinned-write-staged.d.ts.map +1 -0
- package/dist/pinned-write-staged.js +186 -0
- package/dist/pinned-write-types.d.ts +3 -0
- package/dist/pinned-write-types.d.ts.map +1 -1
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +41 -147
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +18 -4
- package/dist/private-producer-handoff-sync.d.ts +14 -0
- package/dist/private-producer-handoff-sync.d.ts.map +1 -0
- package/dist/private-producer-handoff-sync.js +114 -0
- package/dist/private-producer-handoff.d.ts +22 -4
- package/dist/private-producer-handoff.d.ts.map +1 -1
- package/dist/private-producer-handoff.js +140 -77
- package/dist/publish-copy-stage.d.ts +2 -1
- package/dist/publish-copy-stage.d.ts.map +1 -1
- package/dist/publish-copy-stage.js +16 -7
- package/dist/publish-file.d.ts +2 -2
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +58 -98
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +35 -44
- package/dist/replace-file-copy-fallback.d.ts.map +1 -1
- package/dist/replace-file-copy-fallback.js +28 -26
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +13 -22
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +10 -16
- package/dist/replace-file-temp-owner.d.ts +0 -7
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +9 -60
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +9 -13
- package/dist/root-create-input.d.ts +2 -1
- package/dist/root-create-input.d.ts.map +1 -1
- package/dist/root-create-input.js +13 -4
- package/dist/root-directory-creation.d.ts +3 -3
- package/dist/root-directory-creation.d.ts.map +1 -1
- package/dist/root-directory-creation.js +15 -3
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +20 -3
- package/dist/root-file-final-admission.d.ts +1 -1
- package/dist/root-file-final-admission.d.ts.map +1 -1
- package/dist/root-file-final-admission.js +5 -2
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +3 -2
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +78 -27
- package/dist/root-move-noreplace.d.ts +2 -0
- package/dist/root-move-noreplace.d.ts.map +1 -1
- package/dist/root-move-noreplace.js +22 -13
- package/dist/root-options.d.ts +12 -4
- package/dist/root-options.d.ts.map +1 -1
- package/dist/root-path-stat.d.ts.map +1 -1
- package/dist/root-path-stat.js +59 -7
- package/dist/root-read-admission.d.ts.map +1 -1
- package/dist/root-read-admission.js +7 -2
- package/dist/root-remove.d.ts.map +1 -1
- package/dist/root-remove.js +15 -1
- package/dist/root-write-publication.js +1 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +1 -0
- package/dist/secure-file-windows.d.ts +6 -0
- package/dist/secure-file-windows.d.ts.map +1 -1
- package/dist/secure-file-windows.js +34 -117
- package/dist/secure-file.js +2 -2
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +4 -6
- package/dist/sidecar-lock-handle.d.ts +3 -0
- package/dist/sidecar-lock-handle.d.ts.map +1 -1
- package/dist/sidecar-lock-handle.js +6 -0
- package/dist/sidecar-lock-reclaim.d.ts +1 -1
- package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
- package/dist/sidecar-lock-reclaim.js +11 -8
- package/dist/sidecar-lock-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +2 -1
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +3 -5
- package/dist/staged-directory.d.ts +2 -2
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +6 -6
- package/dist/staged-file-settlement.d.ts +17 -0
- package/dist/staged-file-settlement.d.ts.map +1 -0
- package/dist/staged-file-settlement.js +57 -0
- package/dist/strict-file-identity.d.ts +1 -1
- package/dist/strict-file-identity.d.ts.map +1 -1
- package/dist/strict-file-identity.js +9 -9
- package/dist/symlink-parents.d.ts.map +1 -1
- package/dist/symlink-parents.js +2 -27
- package/dist/temp-workspace-owner.js +4 -4
- package/dist/unicode-path.d.ts.map +1 -1
- package/dist/unicode-path.js +3 -0
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +4 -2
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +2 -1
- package/dist/windows-security-bridge.cs +336 -0
- package/dist/windows-security-bridge.ps1 +15 -0
- package/dist/windows-security-command.d.ts +26 -0
- package/dist/windows-security-command.d.ts.map +1 -0
- package/dist/windows-security-command.js +363 -0
- package/dist/windows-security-facts.d.ts +6 -0
- package/dist/windows-security-facts.d.ts.map +1 -0
- package/dist/windows-security-facts.js +108 -0
- package/dist/write-file-handle.d.ts +7 -0
- package/dist/write-file-handle.d.ts.map +1 -1
- package/dist/write-file-handle.js +23 -0
- package/dist/write-open-flags.d.ts.map +1 -1
- package/dist/write-open-flags.js +1 -8
- package/dist/write-queue.d.ts.map +1 -1
- package/dist/write-queue.js +1 -4
- package/docs/advanced.md +71 -2
- package/docs/archive.md +102 -39
- package/docs/atomic.md +29 -5
- package/docs/config.md +6 -2
- package/docs/contributing.md +48 -4
- package/docs/copy.md +2 -0
- package/docs/creation.md +132 -0
- package/docs/durability.md +59 -0
- package/docs/file-contents.md +68 -0
- package/docs/install.md +31 -7
- package/docs/json.md +5 -4
- package/docs/local-roots.md +2 -0
- package/docs/migrating-to-0.5.md +15 -6
- package/docs/migrating-to-0.6.md +9 -4
- package/docs/mutation-policy-proof.md +5 -3
- package/docs/native-helper.md +22 -9
- package/docs/native.md +47 -15
- package/docs/path.md +4 -4
- package/docs/permissions.md +37 -14
- package/docs/public-api.md +5 -0
- package/docs/quickstart.md +1 -1
- package/docs/reading.md +2 -2
- package/docs/regular-file.md +3 -0
- package/docs/root.md +43 -0
- package/docs/secret-file.md +11 -2
- package/docs/secure-file.md +9 -4
- package/docs/sidecar-lock.md +14 -5
- package/docs/staged-file.md +9 -3
- package/docs/store.md +3 -1
- package/docs/temp.md +4 -1
- package/docs/types.md +18 -2
- package/docs/walk.md +7 -0
- package/docs/writing.md +80 -7
- package/package.json +18 -15
package/dist/json.js
CHANGED
|
@@ -3,12 +3,12 @@ import fsSync from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { readFileDescriptorBoundedSync } from "./bounded-read.js";
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
|
-
import { sameFileIdentityForCleanup } from "./file-identity.js";
|
|
7
6
|
import { stringifyJsonDocument } from "./json-stringify.js";
|
|
8
7
|
import { readRegularFile, readRegularFileSync, statRegularFile } from "./regular-file.js";
|
|
9
8
|
import { openRootFileSync } from "./root-file.js";
|
|
10
|
-
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
11
9
|
import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
|
|
10
|
+
import { writeTempFileSync } from "./replace-file-descriptor.js";
|
|
11
|
+
import { SyncAtomicTempOwner } from "./replace-file-temp-owner.js";
|
|
12
12
|
import { admitStandalonePublicationPath } from "./standalone-publication-path.js";
|
|
13
13
|
import { writeTextAtomic } from "./text-atomic.js";
|
|
14
14
|
import { sleep } from "./timing.js";
|
|
@@ -56,42 +56,12 @@ const JSON_DIR_MODE = 0o700;
|
|
|
56
56
|
function getErrorCode(err) {
|
|
57
57
|
return err instanceof Error ? err.code : undefined;
|
|
58
58
|
}
|
|
59
|
-
function trySetSecureMode(
|
|
60
|
-
let fd;
|
|
59
|
+
function trySetSecureMode(fd) {
|
|
61
60
|
try {
|
|
62
|
-
const before = fsSync.lstatSync(pathname, { bigint: true });
|
|
63
|
-
if (before.isSymbolicLink() ||
|
|
64
|
-
!before.isFile() ||
|
|
65
|
-
before.nlink !== 1n ||
|
|
66
|
-
!sameFileIdentityForCleanup(before, expectedIdentity)) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
fd = fsSync.openSync(pathname, resolveReadOpenFlags());
|
|
70
|
-
const opened = fsSync.fstatSync(fd, { bigint: true });
|
|
71
|
-
const current = fsSync.lstatSync(pathname, { bigint: true });
|
|
72
|
-
if (!opened.isFile() ||
|
|
73
|
-
opened.nlink !== 1n ||
|
|
74
|
-
current.isSymbolicLink() ||
|
|
75
|
-
!current.isFile() ||
|
|
76
|
-
current.nlink !== 1n ||
|
|
77
|
-
!sameFileIdentityForCleanup(opened, expectedIdentity) ||
|
|
78
|
-
!sameFileIdentityForCleanup(current, opened)) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
61
|
fsSync.fchmodSync(fd, JSON_FILE_MODE);
|
|
82
62
|
}
|
|
83
63
|
catch {
|
|
84
|
-
// Best-effort mode application
|
|
85
|
-
}
|
|
86
|
-
finally {
|
|
87
|
-
if (fd !== undefined) {
|
|
88
|
-
try {
|
|
89
|
-
fsSync.closeSync(fd);
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
// best-effort cleanup
|
|
93
|
-
}
|
|
94
|
-
}
|
|
64
|
+
// Best-effort mode application stays on the retained staging descriptor.
|
|
95
65
|
}
|
|
96
66
|
}
|
|
97
67
|
function trySyncDirectory(pathname) {
|
|
@@ -114,48 +84,24 @@ function trySyncDirectory(pathname) {
|
|
|
114
84
|
}
|
|
115
85
|
}
|
|
116
86
|
}
|
|
117
|
-
function renameJsonFileWithFallback(
|
|
87
|
+
function renameJsonFileWithFallback(owner, pathname) {
|
|
88
|
+
owner.assertCurrent(fsSync);
|
|
118
89
|
try {
|
|
119
|
-
fsSync.renameSync(
|
|
90
|
+
fsSync.renameSync(owner.pathname, pathname);
|
|
120
91
|
return;
|
|
121
92
|
}
|
|
122
93
|
catch (error) {
|
|
123
|
-
const code = error
|
|
94
|
+
const code = error?.code;
|
|
124
95
|
if (code === "EPERM" || code === "EEXIST") {
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
return fsSync.lstatSync(pathname);
|
|
128
|
-
}
|
|
129
|
-
catch (lstatError) {
|
|
130
|
-
if (lstatError.code === "ENOENT") {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
throw lstatError;
|
|
134
|
-
}
|
|
135
|
-
})();
|
|
136
|
-
if (existing?.isSymbolicLink()) {
|
|
137
|
-
fsSync.rmSync(pathname, { force: true });
|
|
138
|
-
fsSync.renameSync(tmpPath, pathname);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
96
|
+
owner.assertCurrent(fsSync);
|
|
141
97
|
fsSync.rmSync(pathname, { force: true });
|
|
142
|
-
|
|
98
|
+
owner.assertCurrent(fsSync);
|
|
99
|
+
fsSync.renameSync(owner.pathname, pathname);
|
|
143
100
|
return;
|
|
144
101
|
}
|
|
145
102
|
throw error;
|
|
146
103
|
}
|
|
147
104
|
}
|
|
148
|
-
function writeTempJsonFile(pathname, payload) {
|
|
149
|
-
const fd = fsSync.openSync(pathname, "wx", JSON_FILE_MODE);
|
|
150
|
-
try {
|
|
151
|
-
fsSync.writeFileSync(fd, payload, "utf8");
|
|
152
|
-
fsSync.fsyncSync(fd);
|
|
153
|
-
return fsSync.fstatSync(fd, { bigint: true });
|
|
154
|
-
}
|
|
155
|
-
finally {
|
|
156
|
-
fsSync.closeSync(fd);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
105
|
export function tryReadJsonSync(pathname, options = {}) {
|
|
160
106
|
try {
|
|
161
107
|
const raw = readRegularFileSync({
|
|
@@ -174,20 +120,31 @@ export function writeJsonSync(pathname, data) {
|
|
|
174
120
|
const tmpPath = path.format({ ...path.parse(filePath), base: `.fs-safe-${randomUUID()}.tmp` });
|
|
175
121
|
const payload = `${stringifyJsonDocument(data, null, 2)}\n`;
|
|
176
122
|
fsSync.mkdirSync(recursiveMkdirPath(path.dirname(filePath)), { recursive: true, mode: JSON_DIR_MODE });
|
|
123
|
+
const owner = new SyncAtomicTempOwner(tmpPath);
|
|
124
|
+
let originalFailure;
|
|
177
125
|
try {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
126
|
+
owner.start();
|
|
127
|
+
const temp = writeTempFileSync({
|
|
128
|
+
fsModule: fsSync, tempPath: tmpPath, content: payload, mode: JSON_FILE_MODE,
|
|
129
|
+
sync: false, onIdentity: owner.onIdentity,
|
|
130
|
+
});
|
|
131
|
+
owner.adopt(temp);
|
|
132
|
+
owner.assertCurrent(fsSync);
|
|
133
|
+
trySetSecureMode(temp.fd);
|
|
134
|
+
fsSync.fsyncSync(temp.fd);
|
|
135
|
+
renameJsonFileWithFallback(owner, filePath);
|
|
136
|
+
owner.markRenamed();
|
|
137
|
+
owner.assertPublished(fsSync, filePath);
|
|
138
|
+
trySetSecureMode(temp.fd);
|
|
182
139
|
trySyncDirectory(filePath);
|
|
140
|
+
owner.assertPublished(fsSync, filePath);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
originalFailure = { error };
|
|
144
|
+
throw error;
|
|
183
145
|
}
|
|
184
146
|
finally {
|
|
185
|
-
|
|
186
|
-
fsSync.rmSync(tmpPath, { force: true });
|
|
187
|
-
}
|
|
188
|
-
catch {
|
|
189
|
-
// best-effort cleanup when rename does not happen
|
|
190
|
-
}
|
|
147
|
+
owner.finish({ fsModule: fsSync, originalFailure, throwOnCleanupError: false });
|
|
191
148
|
}
|
|
192
149
|
}
|
|
193
150
|
export class JsonFileReadError extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-roots.d.ts","sourceRoot":"","sources":["../src/local-roots.ts"],"names":[],"mappings":"AAQA,OAAO,EAAQ,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAQ3F,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAAG,sBAAsB,GAAG;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,sBAAsB,GAAG;IACnE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;
|
|
1
|
+
{"version":3,"file":"local-roots.d.ts","sourceRoot":"","sources":["../src/local-roots.ts"],"names":[],"mappings":"AAQA,OAAO,EAAQ,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAQ3F,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAAG,sBAAsB,GAAG;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,sBAAsB,GAAG;IACnE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AA+EF,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,oCAAoC,GAC5C,oBAAoB,GAAG,IAAI,CAoC7B;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA6BtC"}
|
package/dist/local-roots.js
CHANGED
|
@@ -71,7 +71,7 @@ function resolveRootRealSync(rootDir) {
|
|
|
71
71
|
assertNoWindowsPathAlias(realPath, "filesystem", "local root uses a Windows filesystem namespace alias");
|
|
72
72
|
return realPath;
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
function prepareLocalRootsInput(options) {
|
|
75
75
|
const label = options.label ?? "local roots";
|
|
76
76
|
const rootDirs = options.roots.map((rootEntry) => resolveLocalRootInput(rootEntry, label));
|
|
77
77
|
let requestedPath;
|
|
@@ -83,6 +83,13 @@ export function resolveLocalPathFromRootsSync(options) {
|
|
|
83
83
|
return null;
|
|
84
84
|
throw error;
|
|
85
85
|
}
|
|
86
|
+
return { label, rootDirs, requestedPath };
|
|
87
|
+
}
|
|
88
|
+
export function resolveLocalPathFromRootsSync(options) {
|
|
89
|
+
const input = prepareLocalRootsInput(options);
|
|
90
|
+
if (!input)
|
|
91
|
+
return null;
|
|
92
|
+
const { label, rootDirs, requestedPath } = input;
|
|
86
93
|
for (const rootDir of rootDirs) {
|
|
87
94
|
const rootReal = resolveRootRealSync(rootDir);
|
|
88
95
|
if (!rootReal) {
|
|
@@ -122,17 +129,17 @@ export function resolveLocalPathFromRootsSync(options) {
|
|
|
122
129
|
}
|
|
123
130
|
export async function readLocalFileFromRoots(options) {
|
|
124
131
|
const maxBytes = normalizeMaxBytes(options.maxBytes);
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
const input = prepareLocalRootsInput(options);
|
|
133
|
+
if (!input || input.rootDirs.length === 0)
|
|
134
|
+
return null;
|
|
135
|
+
const { rootDirs, requestedPath } = input;
|
|
136
|
+
const readOptions = {
|
|
137
|
+
hardlinks: options.hardlinks,
|
|
138
|
+
symlinks: options.symlinks,
|
|
139
|
+
};
|
|
140
|
+
// Omission keeps Root's default cap; one policy snapshot serves every root.
|
|
141
|
+
if (maxBytes !== undefined)
|
|
142
|
+
readOptions.maxBytes = maxBytes;
|
|
136
143
|
for (const rootDir of rootDirs) {
|
|
137
144
|
let scopedRoot;
|
|
138
145
|
try {
|
|
@@ -141,15 +148,6 @@ export async function readLocalFileFromRoots(options) {
|
|
|
141
148
|
catch {
|
|
142
149
|
continue;
|
|
143
150
|
}
|
|
144
|
-
const readOptions = {
|
|
145
|
-
hardlinks: options.hardlinks,
|
|
146
|
-
symlinks: options.symlinks,
|
|
147
|
-
};
|
|
148
|
-
// Leave maxBytes absent when the caller omits it so Root's own default
|
|
149
|
-
// cap remains in force instead of being overwritten by undefined.
|
|
150
|
-
if (maxBytes !== undefined) {
|
|
151
|
-
readOptions.maxBytes = maxBytes;
|
|
152
|
-
}
|
|
153
151
|
try {
|
|
154
152
|
const result = await scopedRoot.readAbsolute(requestedPath, readOptions);
|
|
155
153
|
return { ...result, root: scopedRoot.rootReal };
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import fsSync from "node:fs";
|
|
2
|
-
export type EntryIdentity =
|
|
3
|
-
ctimeMs: number;
|
|
4
|
-
dev: number;
|
|
5
|
-
ino: number;
|
|
6
|
-
mode: number;
|
|
7
|
-
mtimeMs: number;
|
|
8
|
-
nlink: number;
|
|
9
|
-
size: number;
|
|
10
|
-
};
|
|
2
|
+
export type EntryIdentity = Readonly<Pick<fsSync.BigIntStats, "ctimeNs" | "dev" | "ino" | "mode" | "mtimeNs" | "nlink" | "size">>;
|
|
11
3
|
export type CopiedEntryManifest = (EntryIdentity & {
|
|
12
4
|
children: Array<{
|
|
13
5
|
name: string;
|
|
@@ -27,19 +19,13 @@ type CleanupAliasGroup = {
|
|
|
27
19
|
export type CleanupCopiedEntryState = {
|
|
28
20
|
aliasGroups: Map<string, CleanupAliasGroup>;
|
|
29
21
|
};
|
|
30
|
-
export declare function entryIdentity(stat:
|
|
31
|
-
ctimeMs: number;
|
|
32
|
-
dev: number;
|
|
33
|
-
ino: number;
|
|
34
|
-
mode: number;
|
|
35
|
-
mtimeMs: number;
|
|
36
|
-
nlink: number;
|
|
37
|
-
size: number;
|
|
38
|
-
}): EntryIdentity;
|
|
22
|
+
export declare function entryIdentity(stat: EntryIdentity): EntryIdentity;
|
|
39
23
|
export declare function sameIdentity(a: EntryIdentity, b: EntryIdentity): boolean;
|
|
40
24
|
export declare function sourceChangedError(sourcePath: string): Error;
|
|
25
|
+
export declare function inspectSourceEntry(sourcePath: string, observe: () => fsSync.BigIntStats): fsSync.BigIntStats;
|
|
26
|
+
export declare function inspectSourceDirectory(sourcePath: string, expected?: Pick<fsSync.BigIntStats, "dev" | "ino">): fsSync.BigIntStats;
|
|
41
27
|
export declare function assertSourceStillMatches(sourcePath: string, identity: EntryIdentity): Promise<void>;
|
|
42
28
|
export declare function createCleanupCopiedEntryState(sourcePath: string, manifest: CopiedEntryManifest): CleanupCopiedEntryState;
|
|
43
|
-
export declare function cleanupCopiedEntry(sourcePath: string, manifest: CopiedEntryManifest, state: CleanupCopiedEntryState, assertBeforeMutation: () => void): Promise<CleanupCopiedEntryResult>;
|
|
29
|
+
export declare function cleanupCopiedEntry(sourcePath: string, manifest: CopiedEntryManifest, state: CleanupCopiedEntryState, assertBeforeMutation: (() => void) | undefined): Promise<CleanupCopiedEntryResult>;
|
|
44
30
|
export {};
|
|
45
31
|
//# sourceMappingURL=move-path-cleanup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"move-path-cleanup.d.ts","sourceRoot":"","sources":["../src/move-path-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"move-path-cleanup.d.ts","sourceRoot":"","sources":["../src/move-path-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAO7B,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAC1D,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAClE,CAAC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAC3B,CAAC,aAAa,GAAG;IACf,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,mBAAmB,CAAA;KAAE,CAAC,CAAC;IACjE,iBAAiB,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;IACrE,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC,GACF,CAAC,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEvC,KAAK,wBAAwB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpD,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC7C,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,CAUhE;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,CAUxE;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAI5D;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAE5G;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,GACjD,MAAM,CAAC,WAAW,CAWpB;AAED,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,IAAI,CAAC,CAIf;AA0BD,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,mBAAmB,GAC5B,uBAAuB,CAuBzB;AAgED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,uBAAuB,EAC9B,oBAAoB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAC7C,OAAO,CAAC,wBAAwB,CAAC,CA0FnC"}
|
|
@@ -2,14 +2,15 @@ import fsSync from "node:fs";
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
|
+
import { inspectDirectoryIdentitySync } from "./directory-guard.js";
|
|
5
6
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
6
7
|
export function entryIdentity(stat) {
|
|
7
8
|
return {
|
|
8
|
-
|
|
9
|
+
ctimeNs: stat.ctimeNs,
|
|
9
10
|
dev: stat.dev,
|
|
10
11
|
ino: stat.ino,
|
|
11
12
|
mode: stat.mode,
|
|
12
|
-
|
|
13
|
+
mtimeNs: stat.mtimeNs,
|
|
13
14
|
nlink: stat.nlink,
|
|
14
15
|
size: stat.size,
|
|
15
16
|
};
|
|
@@ -20,16 +21,32 @@ export function sameIdentity(a, b) {
|
|
|
20
21
|
a.mode === b.mode &&
|
|
21
22
|
a.nlink === b.nlink &&
|
|
22
23
|
a.size === b.size &&
|
|
23
|
-
a.
|
|
24
|
-
a.
|
|
24
|
+
a.mtimeNs === b.mtimeNs &&
|
|
25
|
+
a.ctimeNs === b.ctimeNs);
|
|
25
26
|
}
|
|
26
27
|
export function sourceChangedError(sourcePath) {
|
|
27
28
|
return Object.assign(new Error(`Source changed during move fallback: ${sourcePath}`), {
|
|
28
29
|
code: "ESTALE",
|
|
29
30
|
});
|
|
30
31
|
}
|
|
32
|
+
export function inspectSourceEntry(sourcePath, observe) {
|
|
33
|
+
return inspectFileIdentitySync(observe, undefined, process.platform, () => sourceChangedError(sourcePath));
|
|
34
|
+
}
|
|
35
|
+
export function inspectSourceDirectory(sourcePath, expected) {
|
|
36
|
+
try {
|
|
37
|
+
return inspectDirectoryIdentitySync(sourcePath, expected);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
const code = error?.code;
|
|
41
|
+
if (code === "ENOENT" || code === "ENOTDIR" ||
|
|
42
|
+
(error instanceof FsSafeError && (error.code === "path-mismatch" || error.code === "not-file"))) {
|
|
43
|
+
throw sourceChangedError(sourcePath);
|
|
44
|
+
}
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
31
48
|
export async function assertSourceStillMatches(sourcePath, identity) {
|
|
32
|
-
if (!sameIdentity(identity,
|
|
49
|
+
if (!sameIdentity(identity, inspectSourceEntry(sourcePath, () => fsSync.lstatSync(sourcePath, { bigint: true })))) {
|
|
33
50
|
throw sourceChangedError(sourcePath);
|
|
34
51
|
}
|
|
35
52
|
}
|
|
@@ -43,7 +60,7 @@ function collectAliasCandidates(sourcePath, manifest, candidates) {
|
|
|
43
60
|
}
|
|
44
61
|
return;
|
|
45
62
|
}
|
|
46
|
-
if (manifest.nlink <=
|
|
63
|
+
if (manifest.nlink <= 1n) {
|
|
47
64
|
return;
|
|
48
65
|
}
|
|
49
66
|
const key = identityKey(manifest);
|
|
@@ -76,15 +93,26 @@ function sameOwnedUnlinkTransition(before, after) {
|
|
|
76
93
|
before.ino === after.ino &&
|
|
77
94
|
before.mode === after.mode &&
|
|
78
95
|
before.size === after.size &&
|
|
79
|
-
before.
|
|
80
|
-
before.nlink >
|
|
81
|
-
after.nlink === before.nlink -
|
|
82
|
-
after.
|
|
96
|
+
before.mtimeNs === after.mtimeNs &&
|
|
97
|
+
before.nlink > 0n &&
|
|
98
|
+
after.nlink === before.nlink - 1n &&
|
|
99
|
+
after.ctimeNs >= before.ctimeNs);
|
|
83
100
|
}
|
|
84
101
|
function poisonAliasGroup(group) {
|
|
85
102
|
group.stale = true;
|
|
86
103
|
return "stale";
|
|
87
104
|
}
|
|
105
|
+
function inspectCleanupLeaf(sourcePath, expected) {
|
|
106
|
+
let mismatch;
|
|
107
|
+
try {
|
|
108
|
+
return inspectFileIdentitySync(() => fsSync.lstatSync(sourcePath, { bigint: true }), expected, process.platform, () => mismatch = sourceChangedError(sourcePath));
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (mismatch !== undefined && error === mismatch)
|
|
112
|
+
return undefined;
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
88
116
|
async function observeOwnedAliasUnlink(sourcePath, group) {
|
|
89
117
|
group.remainingPaths.delete(sourcePath);
|
|
90
118
|
const remainingPath = group.remainingPaths.values().next().value;
|
|
@@ -93,7 +121,7 @@ async function observeOwnedAliasUnlink(sourcePath, group) {
|
|
|
93
121
|
}
|
|
94
122
|
let observed;
|
|
95
123
|
try {
|
|
96
|
-
observed =
|
|
124
|
+
observed = inspectCleanupLeaf(remainingPath, group.expected);
|
|
97
125
|
}
|
|
98
126
|
catch (error) {
|
|
99
127
|
if (error?.code === "ENOENT") {
|
|
@@ -101,11 +129,10 @@ async function observeOwnedAliasUnlink(sourcePath, group) {
|
|
|
101
129
|
}
|
|
102
130
|
throw error;
|
|
103
131
|
}
|
|
104
|
-
|
|
105
|
-
if (!sameOwnedUnlinkTransition(group.expected, observedIdentity)) {
|
|
132
|
+
if (!observed || !sameOwnedUnlinkTransition(group.expected, observed)) {
|
|
106
133
|
return poisonAliasGroup(group);
|
|
107
134
|
}
|
|
108
|
-
group.expected =
|
|
135
|
+
group.expected = entryIdentity(observed);
|
|
109
136
|
return "removed";
|
|
110
137
|
}
|
|
111
138
|
function mergeCleanupResults(a, b) {
|
|
@@ -130,12 +157,16 @@ export async function cleanupCopiedEntry(sourcePath, manifest, state, assertBefo
|
|
|
130
157
|
// A same-inode directory can gain unrelated children after commit. Still
|
|
131
158
|
// clean manifest children so the fallback does not duplicate copied files.
|
|
132
159
|
let result = "removed";
|
|
160
|
+
const assertBeforeChildMutation = assertBeforeMutation ? () => {
|
|
161
|
+
assertBeforeMutation();
|
|
162
|
+
inspectSourceDirectory(sourcePath, manifest.directoryIdentity);
|
|
163
|
+
} : undefined;
|
|
133
164
|
for (const child of manifest.children) {
|
|
134
|
-
result = mergeCleanupResults(result, await cleanupCopiedEntry(path.join(sourcePath, child.name), child.manifest, state,
|
|
165
|
+
result = mergeCleanupResults(result, await cleanupCopiedEntry(path.join(sourcePath, child.name), child.manifest, state, assertBeforeChildMutation));
|
|
135
166
|
}
|
|
136
167
|
// Child cleanup and the caller's authority check can replace the directory.
|
|
137
168
|
// Keep the final exact observation after both, immediately before removal.
|
|
138
|
-
assertBeforeMutation();
|
|
169
|
+
assertBeforeMutation?.();
|
|
139
170
|
try {
|
|
140
171
|
currentStat = inspectFileIdentitySync(() => fsSync.lstatSync(sourcePath, { bigint: true }), manifest.directoryIdentity);
|
|
141
172
|
}
|
|
@@ -166,9 +197,10 @@ export async function cleanupCopiedEntry(sourcePath, manifest, state, assertBefo
|
|
|
166
197
|
if (aliasGroup?.stale) {
|
|
167
198
|
return "stale";
|
|
168
199
|
}
|
|
200
|
+
const expected = aliasGroup?.expected ?? manifest;
|
|
169
201
|
let currentStat;
|
|
170
202
|
try {
|
|
171
|
-
currentStat =
|
|
203
|
+
currentStat = inspectCleanupLeaf(sourcePath, expected);
|
|
172
204
|
}
|
|
173
205
|
catch (error) {
|
|
174
206
|
if (error?.code === "ENOENT") {
|
|
@@ -176,11 +208,15 @@ export async function cleanupCopiedEntry(sourcePath, manifest, state, assertBefo
|
|
|
176
208
|
}
|
|
177
209
|
throw error;
|
|
178
210
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
211
|
+
for (let observation = 0;; observation++) {
|
|
212
|
+
if (!currentStat || !sameIdentity(expected, currentStat)) {
|
|
213
|
+
return aliasGroup ? poisonAliasGroup(aliasGroup) : "stale";
|
|
214
|
+
}
|
|
215
|
+
if (observation || !assertBeforeMutation)
|
|
216
|
+
break;
|
|
217
|
+
assertBeforeMutation();
|
|
218
|
+
currentStat = inspectCleanupLeaf(sourcePath, expected);
|
|
182
219
|
}
|
|
183
|
-
assertBeforeMutation();
|
|
184
220
|
await fs.unlink(sourcePath);
|
|
185
221
|
return aliasGroup
|
|
186
222
|
? await observeOwnedAliasUnlink(sourcePath, aliasGroup)
|
package/dist/move-path.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"move-path.d.ts","sourceRoot":"","sources":["../src/move-path.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"move-path.d.ts","sourceRoot":"","sources":["../src/move-path.ts"],"names":[],"mappings":"AA2BA,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC,CAAC;AAEH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,qFAAqF;IACrF,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,qFAAqF;IACrF,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,IAAI,CAAC;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,KAAK,sBAAsB,GAAG,cAAc,GAAG,uBAAuB,CAAC;AAGvE,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,sBAAsB,GAAG,SAAS,CASpC;AA4RD,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,IAAI,CAAC,CA2If"}
|